llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: Erich Keane (erichkeane)

<details>
<summary>Changes</summary>

On bitint types that are not powers of 2, we have to represent them as an 
array. This patch modifies 'convertTypeForMemory' to do that. However, that 
ends up causing a couple of problems, that this also ends up fixing:

First: constant init needs to also lower to this type/get that correct,
  so this introduces 'getBitIntStorageAttr' to manage that

Second: The 'copy' op lowering was getting its layout from the lowered type, 
which is no longer correct.  Since this is suposed to be the same as what we 
get from CIR, this is jsut switched to use that instead.

Third: this ran into an issue with cir.copy in LoweringPrepare where we didn't 
properly copy the alignment over.  The result was our copy operation didn't get 
alignment correct.  This patch fixes that too.

Fourth: Load/Store/VecMaskedLoad all had to change how they got the type for 
their lowering.  Since what they care about is actually the effecitve 'type' 
itself and not the actual type of the memory the case of the array-lowering, 
this patch introduces convertTypeForLoadStore, which is the effective memory 
type(no cast required, since LLVM-IR doesn't care!), rather than the array type.

ALL the above matches classic codegen.

AI Disclosure: I went back and forth with analysis with Claude on this one, and 
it wrote most of the tests, but I did every single check-line :)

---

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


11 Files Affected:

- (modified) clang/include/clang/CIR/LoweringHelpers.h (+13) 
- (modified) clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp (+7-1) 
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+27-20) 
- (modified) clang/lib/CIR/Lowering/LoweringHelpers.cpp (+45-4) 
- (modified) clang/test/CIR/CodeGen/agg-init-constexpr.cpp (+2-2) 
- (modified) clang/test/CIR/CodeGen/array.cpp (+2-2) 
- (removed) clang/test/CIR/CodeGen/bitint-split-storage-nyi.c (-65) 
- (added) clang/test/CIR/CodeGen/bitint-wide.c (+145) 
- (modified) clang/test/CIR/CodeGen/local-const-aggregate-name-clash.cpp (+1-1) 
- (modified) clang/test/CIR/CodeGen/loop.cpp (+2-2) 
- (modified) clang/test/CIR/CodeGenCXX/sizeof-pack.cpp (+2-2) 


``````````diff
diff --git a/clang/include/clang/CIR/LoweringHelpers.h 
b/clang/include/clang/CIR/LoweringHelpers.h
index fe61db3fc5d25..bfd1182aa6489 100644
--- a/clang/include/clang/CIR/LoweringHelpers.h
+++ b/clang/include/clang/CIR/LoweringHelpers.h
@@ -80,4 +80,17 @@ mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value 
lhs, unsigned rhs);
 mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter,
                                 mlir::DataLayout const &dataLayout,
                                 mlir::Type type);
+
+/// The type of a load/store's *value*, as opposed to convertTypeForMemory's
+/// type of the memory it lives in. The two are effectively identical except
+/// with split-storage bit-int.
+mlir::Type convertTypeForLoadStore(const mlir::TypeConverter &converter,
+                                   mlir::DataLayout const &dataLayout,
+                                   mlir::Type type);
+
+// Convert a bit-int value to its llvm value, which can be either an array, or
+// just a large-power-of-2 integer.
+mlir::Attribute getBitIntStorageAttr(mlir::ConversionPatternRewriter &rewriter,
+                                     cir::IntAttr attr,
+                                     const mlir::DataLayout &dataLayout);
 #endif
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp 
b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 2ab71608329ab..b0e6a276efac4 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -2378,7 +2378,13 @@ void 
LoweringPreparePass::lowerStoreOfConstAggregate(cir::StoreOp op) {
       cir::GetGlobalOp::create(builder, op.getLoc(), ptrTy, gv.getSymName());
 
   // Replace store with copy.
-  builder.createCopy(op.getAddr(), globalPtr);
+  cir::CopyOp copyOp = builder.createCopy(op.getAddr(), globalPtr);
+
+  cir::CIRDataLayout dataLayout(mlirModule);
+  if (alloca.getAlignment() != dataLayout.getABITypeAlign(ty).value()) {
+    copyOp.setDstAlignment(alloca.getAlignment());
+    copyOp.setSrcAlignment(alloca.getAlignment());
+  }
 
   // Erase the original store.
   op.erase();
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 6c7166b4aa243..c115b79cb62e7 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -297,10 +297,10 @@ mlir::LogicalResult 
CIRToLLVMCopyOpLowering::matchAndRewrite(
       op.getCopySizeInBytes(layout));
   assert(!cir::MissingFeatures::aggValueSlotVolatile());
 
-  uint64_t dstTypeAlign = dataLayout.getTypeABIAlignment(convertTypeForMemory(
-      *getTypeConverter(), dataLayout, op.getDst().getType().getPointee()));
-  uint64_t srcTypeAlign = dataLayout.getTypeABIAlignment(convertTypeForMemory(
-      *getTypeConverter(), dataLayout, op.getSrc().getType().getPointee()));
+  uint64_t dstTypeAlign =
+      dataLayout.getTypeABIAlignment(op.getDst().getType().getPointee());
+  uint64_t srcTypeAlign =
+      dataLayout.getTypeABIAlignment(op.getSrc().getType().getPointee());
 
   mlir::NamedAttribute dstAlignAttr = rewriter.getNamedAttr(
       mlir::LLVM::LLVMDialect::getAlignAttrName(),
@@ -624,6 +624,14 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::BoolAttr 
boolAttr) {
 mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) {
   mlir::Location loc = parentOp->getLoc();
   mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
+
+  if (auto intTy = mlir::dyn_cast<cir::IntType>(intAttr.getType());
+      intTy && intTy.isBitInt()) {
+    mlir::Type biTy = convertTypeForMemory(*converter, layout, intTy);
+    return mlir::LLVM::ConstantOp::create(
+        rewriter, loc, biTy, getBitIntStorageAttr(rewriter, intAttr, layout));
+  }
+
   // Materialize the value at its literal width, then widen to the in-memory
   // storage type (a no-op except for _BitInt) so aggregate members built here
   // match the iM struct/array fields produced by convertTypeForMemory.
@@ -1057,9 +1065,9 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::ZeroAttr 
attr) {
 // require region initialization.
 class GlobalInitAttrRewriter {
 public:
-  GlobalInitAttrRewriter(mlir::Type type,
+  GlobalInitAttrRewriter(mlir::Type type, mlir::DataLayout const &dataLayout,
                          mlir::ConversionPatternRewriter &rewriter)
-      : llvmType(type), rewriter(rewriter) {}
+      : llvmType(type), dataLayout(dataLayout), rewriter(rewriter) {}
 
   mlir::Attribute visit(mlir::Attribute attr) {
     return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(attr)
@@ -1069,17 +1077,15 @@ class GlobalInitAttrRewriter {
   }
 
   mlir::Attribute visitCirAttr(cir::IntAttr attr) {
-    // A _BitInt(N) global stores its value in a padded integer iM; sign/zero-
-    // extend the APInt to that width (a no-op for plain integers, whose value
-    // width already matches llvmType) so the IntegerAttr is well-typed.
+    // A split-storage _BitInt's memory representation is a byte array (see
+    // convertTypeForMemory), not a scalar, so its constant must be built as
+    // raw bytes rather than a single sign/zero-extended IntegerAttr.
+    if (auto intTy = mlir::dyn_cast<cir::IntType>(attr.getType());
+        intTy && intTy.isBitInt())
+      return getBitIntStorageAttr(rewriter, attr, dataLayout);
     llvm::APInt val = attr.getValue();
-    auto destTy = mlir::cast<mlir::IntegerType>(llvmType);
-    if (val.getBitWidth() != destTy.getWidth()) {
-      cir::IntTypeInterface cirIntTy = attr.getType();
-      val = cirIntTy.isSigned() ? val.sext(destTy.getWidth())
-                                : val.zext(destTy.getWidth());
-    }
-    return rewriter.getIntegerAttr(llvmType, val);
+
+    return rewriter.getIntegerAttr(llvmType, attr.getValue());
   }
 
   mlir::Attribute visitCirAttr(cir::FPAttr attr) {
@@ -1092,6 +1098,7 @@ class GlobalInitAttrRewriter {
 
 private:
   mlir::Type llvmType;
+  const mlir::DataLayout &dataLayout;
   mlir::ConversionPatternRewriter &rewriter;
 };
 
@@ -2372,7 +2379,7 @@ mlir::LogicalResult 
CIRToLLVMLoadOpLowering::matchAndRewrite(
     cir::LoadOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
   const mlir::Type llvmTy =
-      convertTypeForMemory(*getTypeConverter(), dataLayout, op.getType());
+      convertTypeForLoadStore(*getTypeConverter(), dataLayout, op.getType());
   if (!llvmTy)
     return op.emitError()
            << "NYI: lowering load of a type with no memory representation";
@@ -2407,7 +2414,7 @@ 
cir::direct::CIRToLLVMVecMaskedLoadOpLowering::matchAndRewrite(
     cir::VecMaskedLoadOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
   const mlir::Type llvmResTy =
-      convertTypeForMemory(*getTypeConverter(), dataLayout, op.getType());
+      convertTypeForLoadStore(*getTypeConverter(), dataLayout, op.getType());
   if (!llvmResTy)
     return op.emitError()
            << "NYI: lowering masked load of a type with no memory "
@@ -2431,7 +2438,7 @@ mlir::LogicalResult 
CIRToLLVMStoreOpLowering::matchAndRewrite(
   mlir::LLVM::AtomicOrdering memorder = getLLVMMemOrder(op.getMemOrder());
   mlir::Type valueType = op.getValue().getType();
   const mlir::Type llvmTy =
-      convertTypeForMemory(*getTypeConverter(), dataLayout, valueType);
+      convertTypeForLoadStore(*getTypeConverter(), dataLayout, valueType);
   if (!llvmTy)
     return op.emitError()
            << "NYI: lowering store of a type with no memory representation";
@@ -3083,7 +3090,7 @@ mlir::LogicalResult 
CIRToLLVMGlobalOpLowering::matchAndRewrite(
 
   if (init.has_value()) {
     if (mlir::isa<cir::FPAttr, cir::IntAttr, cir::BoolAttr>(init.value())) {
-      GlobalInitAttrRewriter initRewriter(llvmType, rewriter);
+      GlobalInitAttrRewriter initRewriter(llvmType, dataLayout, rewriter);
       init = initRewriter.visit(init.value());
       // If initRewriter returned a null attribute, init will have a value but
       // the value will be null. If that happens, initRewriter didn't handle 
the
diff --git a/clang/lib/CIR/Lowering/LoweringHelpers.cpp 
b/clang/lib/CIR/Lowering/LoweringHelpers.cpp
index 0b64a37cb6bf4..005a904f94f71 100644
--- a/clang/lib/CIR/Lowering/LoweringHelpers.cpp
+++ b/clang/lib/CIR/Lowering/LoweringHelpers.cpp
@@ -36,6 +36,31 @@ bool isSplitStorageBitInt(cir::IntType ty, const 
mlir::DataLayout &dataLayout) {
 }
 } // namespace
 
+mlir::Attribute getBitIntStorageAttr(mlir::ConversionPatternRewriter &rewriter,
+                                     cir::IntAttr attr,
+                                     const mlir::DataLayout &dataLayout) {
+  auto intTy = mlir::cast<cir::IntType>(attr.getType());
+  unsigned storageBits = intTy.getStorageTypeWidth(dataLayout);
+  llvm::APInt val = attr.getValue();
+  val = intTy.isSigned() ? val.sext(storageBits) : val.zext(storageBits);
+
+  if (!isSplitStorageBitInt(intTy, dataLayout))
+    return rewriter.getIntegerAttr(
+        mlir::IntegerType::get(intTy.getContext(), storageBits), val);
+
+  // If we have to do split storage, we are an array of bytes.  Split this up
+  // into the array that matches convertTypeForMemory.
+  unsigned numBytes = storageBits / 8;
+  llvm::SmallVector<mlir::APInt> bytes;
+  bytes.reserve(numBytes);
+  for (unsigned i = 0; i != numBytes; ++i)
+    bytes.emplace_back(8, val.extractBitsAsZExtValue(8, i * 8));
+
+  auto i8Ty = mlir::IntegerType::get(intTy.getContext(), 8);
+  return mlir::DenseElementsAttr::get(
+      mlir::RankedTensorType::get({numBytes}, i8Ty), bytes);
+}
+
 mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter,
                                 mlir::DataLayout const &dataLayout,
                                 mlir::Type type) {
@@ -57,13 +82,15 @@ mlir::Type convertTypeForMemory(const mlir::TypeConverter 
&converter,
 
   // _BitInt(N) keeps its literal width as a value but is stored in a padded
   // integer iM in memory, the same way bool is i1 as a value and i8 in
-  // memory. The byte-array storage form for wide split widths is not
-  // implemented; a null return signals that, and op lowerings turn it into
-  // errorNYI.
+  // memory. When iM's own LLVM alloc size would overshoot the AST-exact
+  // M/8 byte count (isSplitStorageBitInt), use a byte array instead so the
+  // size stays exact.
   if (auto intTy = mlir::dyn_cast<cir::IntType>(type);
       intTy && intTy.isBitInt()) {
     if (isSplitStorageBitInt(intTy, dataLayout))
-      return {};
+      return mlir::LLVM::LLVMArrayType::get(
+          mlir::IntegerType::get(type.getContext(), 8),
+          intTy.getStorageTypeWidth(dataLayout) / 8);
     return mlir::IntegerType::get(type.getContext(),
                                   intTy.getStorageTypeWidth(dataLayout));
   }
@@ -71,6 +98,20 @@ mlir::Type convertTypeForMemory(const mlir::TypeConverter 
&converter,
   return converter.convertType(type);
 }
 
+mlir::Type convertTypeForLoadStore(const mlir::TypeConverter &converter,
+                                   mlir::DataLayout const &dataLayout,
+                                   mlir::Type type) {
+  // A split-storage _BitInt's memory type is a byte array (see
+  // convertTypeForMemory), but a load/store must still access the whole
+  // integer as-is.
+  if (auto intTy = mlir::dyn_cast<cir::IntType>(type);
+      intTy && intTy.isBitInt())
+    return mlir::IntegerType::get(type.getContext(),
+                                  intTy.getStorageTypeWidth(dataLayout));
+
+  return convertTypeForMemory(converter, dataLayout, type);
+}
+
 static unsigned getIntOrBoolBitWidth(mlir::Type ty) {
   if (auto intTy = mlir::dyn_cast<cir::IntType>(ty))
     return intTy.getWidth();
diff --git a/clang/test/CIR/CodeGen/agg-init-constexpr.cpp 
b/clang/test/CIR/CodeGen/agg-init-constexpr.cpp
index 1fab703ff893c..250d10faa6e1d 100644
--- a/clang/test/CIR/CodeGen/agg-init-constexpr.cpp
+++ b/clang/test/CIR/CodeGen/agg-init-constexpr.cpp
@@ -23,13 +23,13 @@ extern "C" void construct() {
 // CIR-LABEL: construct()
 // CIR-NEXT: %[[WC_ALLOCA:.*]] = cir.alloca "c" {{.*}} : 
!cir.ptr<!rec_WithCtor>
 // CIR-NEXT: %[[GET_GLOBAL:.*]] = cir.get_global @__const.construct.c : 
!cir.ptr<!rec_WithCtor>
-// CIR-NEXT: cir.copy %[[GET_GLOBAL]] to %[[WC_ALLOCA]] : 
!cir.ptr<!rec_WithCtor>
+// CIR-NEXT: cir.copy %[[GET_GLOBAL]] align(8) to %[[WC_ALLOCA]] align(8) : 
!cir.ptr<!rec_WithCtor>
 // CIR-NEXT: cir.return
 
 // LLVM: @__const.construct.c = private constant %struct.WithCtor <{ i32 4, [4 
x i8] zeroinitializer, i64 10, %struct.HasVal { i32 5 }, [4 x i8] 
zeroinitializer }>
 // LLVM-LABEL: construct()
 // LLVM-NEXT: %[[WC_ALLOCA:.*]] = alloca %struct.WithCtor
-// LLVM-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %1, ptr align 1 
@__const.construct.c, i64 24, i1 false)
+// LLVM-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %1, ptr align 8 
@__const.construct.c, i64 24, i1 false)
 // LLVM-NEXT: ret void
 
 // OGCG-LABEL: construct()
diff --git a/clang/test/CIR/CodeGen/array.cpp b/clang/test/CIR/CodeGen/array.cpp
index 4cb3f6e0b178d..c17ce8f30d771 100644
--- a/clang/test/CIR/CodeGen/array.cpp
+++ b/clang/test/CIR/CodeGen/array.cpp
@@ -494,10 +494,10 @@ void array_with_complex_elements() {
 
 // CIR: %[[ARR_ADDR:.*]] = cir.alloca "arr" {{.*}} init : 
!cir.ptr<!cir.array<!cir.complex<!cir.float> x 2>>
 // CIR: %[[CONST:.*]] = cir.get_global @[[COMPLEX_ARR]] : 
!cir.ptr<!cir.array<!cir.complex<!cir.float> x 2>>
-// CIR: cir.copy %[[CONST]] to %[[ARR_ADDR]] : 
!cir.ptr<!cir.array<!cir.complex<!cir.float> x 2>>
+// CIR: cir.copy %[[CONST]] align(16) to %[[ARR_ADDR]] align(16) : 
!cir.ptr<!cir.array<!cir.complex<!cir.float> x 2>>
 
 // LLVM: %[[ARR_ADDR:.*]] = alloca [2 x { float, float }], align 16
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[ARR_ADDR]], ptr align 
4 @[[COMPLEX_ARR:.*]], i64 16, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %[[ARR_ADDR]], ptr 
align 16 @[[COMPLEX_ARR:.*]], i64 16, i1 false)
 
 // OGCG: %[[ARR_ADDR:.*]] = alloca [2 x { float, float }], align 16
 // OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %[[ARR_ADDR]], ptr 
align 16 @__const._Z27array_with_complex_elementsv.arr, i64 16, i1 false)
diff --git a/clang/test/CIR/CodeGen/bitint-split-storage-nyi.c 
b/clang/test/CIR/CodeGen/bitint-split-storage-nyi.c
deleted file mode 100644
index f8e3d3de5da07..0000000000000
--- a/clang/test/CIR/CodeGen/bitint-split-storage-nyi.c
+++ /dev/null
@@ -1,65 +0,0 @@
-// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm 
-DGLOBAL %s -o - 2>&1 | FileCheck %s --check-prefix=GLOBAL
-// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm 
-DALLOCA %s -o - 2>&1 | FileCheck %s --check-prefix=ALLOCA
-// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm 
-DSTORE %s -o - 2>&1 | FileCheck %s --check-prefix=STORE
-// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm 
-DLOAD %s -o - 2>&1 | FileCheck %s --check-prefix=LOAD
-// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm 
-DSTRUCT %s -o - 2>&1 | FileCheck %s --check-prefix=STRUCT
-// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm 
-DARRAY %s -o - 2>&1 | FileCheck %s --check-prefix=ARRAY
-// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm 
-DPARAM %s -o - 2>&1 | FileCheck %s --check-prefix=PARAM
-// RUN: not %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm 
-DRETURN %s -o - 2>&1 | FileCheck %s --check-prefix=RETURN
-
-#ifdef GLOBAL
-signed _BitInt(129) g129 = 1;
-// GLOBAL: NYI: lowering global of a type with no memory representation
-#endif
-
-#ifdef ALLOCA
-int use_local(int a) {
-  signed _BitInt(129) x = a;
-  return (int)x;
-}
-// ALLOCA: NYI: lowering alloca of a type with no memory representation
-#endif
-
-#ifdef STORE
-void store_lit(signed _BitInt(129) *p) { *p = (signed _BitInt(129))1; }
-// STORE: NYI: lowering store of a type with no memory representation
-#endif
-
-#ifdef LOAD
-int load_cmp(signed _BitInt(129) *p) { return *p != 0; }
-// LOAD: NYI: lowering load of a type with no memory representation
-#endif
-
-#ifdef STRUCT
-// FIXME: Make sure we test that the layout of this and the array struct are
-// 'correct' when this lowering is completed.
-struct HasWide129 {
-  int i;
-  signed _BitInt(129) bi;
-};
-struct HasWide129 g_struct;
-// STRUCT: NYI: lowering global of a type with no memory representation
-#endif
-
-#ifdef ARRAY
-struct HasWide129Array {
-  int i;
-  signed _BitInt(129) bi[2];
-};
-struct HasWide129Array g_array;
-// ARRAY: NYI: lowering global of a type with no memory representation
-#endif
-
-#ifdef PARAM
-// A split-storage width passed by value classifies Indirect, so the width
-// appears as the byval pointee.
-void take_param(signed _BitInt(129) x) {}
-// PARAM: NYI: lowering a byval/sret/byref argument whose pointee type has no 
memory representation
-#endif
-
-#ifdef RETURN
-// Returned by value it classifies Indirect too, so the width appears as the
-// sret pointee.
-signed _BitInt(129) ret_wide(void) { return 1; }
-// RETURN: NYI: lowering a byval/sret/byref argument whose pointee type has no 
memory representation
-#endif
diff --git a/clang/test/CIR/CodeGen/bitint-wide.c 
b/clang/test/CIR/CodeGen/bitint-wide.c
new file mode 100644
index 0000000000000..07b35fa0bc17f
--- /dev/null
+++ b/clang/test/CIR/CodeGen/bitint-wide.c
@@ -0,0 +1,145 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t-cir.ll
+// RUN: FileCheck --check-prefixes=LLVM,CIRONLY --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefixes=LLVM,OGCG --input-file=%t.ll %s
+
+unsigned _BitInt(200) w200 = 5;
+// CIR-DAG: cir.global external @w200 = #cir.int<5> : !cir.int<u, 200, bitint> 
{alignment = 8 : i64}
+// LLVM-DAG: @w200 = global i256 5, align 8
+signed _BitInt(256) w256 = -1;
+// CIR-DAG: cir.global external @w256 = #cir.int<-1> : !s256i_bitint 
{alignment = 8 : i64}
+// LLVM-DAG: @w256 = global i256 -1, align 8
+
+signed _BitInt(129) g_neg = -1;
+// CIR-DAG: cir.global external @g_neg = #cir.int<-1> : !cir.int<s, 129, 
bitint> {alignment = 8 : i64}
+// LLVM-dAG: @g_neg = global [24 x i8] 
c"\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF", 
align 8
+
+struct HasWide129 {
+  int i;
+  signed _BitInt(129) bi;
+};
+struct HasWide129 g_struct = {7, -1};
+// CIR-DAG: cir.global external @g_struct = #cir.const_record<{#cir.int<7> : 
!s32i, #cir.zero : !cir.array<!u8i x 4>, #cir.int<-1> : !cir.int<s, 129, 
bitint>}> : !rec_HasWide129 {alignment = 8 : i64}
+// Note: CIR packs this, but classic codegen doesn't.  Layout is still
+// identical, but there is a slight IR difference.
+// LLVM-DAG: %struct.HasWide129 = type {{[<]?}}{ i32, [4 x i8], [24 x i8] 
}{{[>]?}}
+// LLVM-DAG: @g_struct = global %struct.HasWide129 {{[<]?}}{ i32 7, [4 x i8] 
zeroinitializer, [24 x i8] 
c"\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF" 
}{{[>]?}}, align 8
+
+signed _BitInt(129) g_arr[2] = {-1, -2};
+// CIR-DAG: cir.global external @g_arr = #cir.const_array<[#cir.int<-1> : 
!cir.int<s, 129, bitint>, #cir.int<-2> : !cir.int<s, 129, bitint>]> : 
!cir.array<!cir.int<s, 129, bitint> x 2> {alignment = 16 : i64}
+// LLVM-DAG: @g_arr = global [2 x [24 x i8]] {{\[\[}}24 x i8] 
c"\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF", 
[24 x i8] 
c"\FE\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF"], 
align 16
+
+struct HasWide129Array {
+  int i;
+  signed _BitInt(129) bi[2];
+};
+struct HasWide129Array g_arr2 = {7, {-1, -2}};
+// CIR-DAG: cir.global external @g_arr2 = #cir.const_record<{#cir.int<7> : 
!s32i, #cir.zero : !cir.array<!u8i x 4>, #cir.const_array<[#cir.int<-1> : 
!cir.int<s, 129, bitint>, #cir.int<-2> : !cir.int<s, 129, bitint>]> : 
!cir.array<!cir.int<s, 129, bitint> x 2>}> : !rec_HasWide129Array {alignment = 
8 : i64}
+// LLVM-DAG: %struct.HasWide129Array = type {{[<]?}}{ i32, [4 x i8], [2 x [24 
x i8]] }{{[>]?}}
+// LLVM-DAG: @g_arr2 = global %struct.HasWide129Array {{[<]?}}{ i32 7, [4 x 
i8] zeroinitializer, [2 x [24 x i8]] {{\[\[}}24 x i8] 
c"\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/225470
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to