[clang] [CIR] Add alignment support for global, store, and load ops (PR #141163)

via cfe-commits cfe-commits at lists.llvm.org
Thu May 22 16:49:45 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Andy Kaylor (andykaylor)

<details>
<summary>Changes</summary>

This adds alignment support for GlobalOp, LoadOp, and StoreOp.

Tests which failed because cir.store/cir.load now print alignment were updated with wildcard matches, except where the alignment was relevant to the test. Tests which check for cir.store/cir.load in cases that don't have explicit alignment were not updated.

New tests for alignment are alignment.c, align-load.c, and align-store.c.


---

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


53 Files Affected:

- (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+9-14) 
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+10-3) 
- (modified) clang/include/clang/CIR/MissingFeatures.h (+5-3) 
- (modified) clang/lib/CIR/CodeGen/CIRGenBuilder.h (+21) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+8-9) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp (+1-1) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+1-1) 
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+42-5) 
- (modified) clang/lib/CIR/CodeGen/CIRGenStmt.cpp (+2-1) 
- (modified) clang/lib/CIR/Dialect/IR/CIRTypes.cpp (+6) 
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+8-8) 
- (added) clang/test/CIR/CodeGen/align-load.c (+96) 
- (added) clang/test/CIR/CodeGen/align-store.c (+94) 
- (added) clang/test/CIR/CodeGen/alignment.c (+26) 
- (modified) clang/test/CIR/CodeGen/array.cpp (+46-46) 
- (modified) clang/test/CIR/CodeGen/basic.c (+24-24) 
- (modified) clang/test/CIR/CodeGen/basic.cpp (+37-37) 
- (modified) clang/test/CIR/CodeGen/binassign.c (+4-4) 
- (modified) clang/test/CIR/CodeGen/binop.cpp (+40-40) 
- (modified) clang/test/CIR/CodeGen/call.cpp (+1-1) 
- (modified) clang/test/CIR/CodeGen/cast.cpp (+4-4) 
- (modified) clang/test/CIR/CodeGen/cmp.cpp (+50-50) 
- (modified) clang/test/CIR/CodeGen/comma.c (+5-5) 
- (modified) clang/test/CIR/CodeGen/compound_assign.cpp (+10-10) 
- (modified) clang/test/CIR/CodeGen/forrange.cpp (+24-24) 
- (modified) clang/test/CIR/CodeGen/if.cpp (+21-21) 
- (modified) clang/test/CIR/CodeGen/local-vars.cpp (+14-13) 
- (modified) clang/test/CIR/CodeGen/loop.cpp (+33-33) 
- (modified) clang/test/CIR/CodeGen/namespace.cpp (+3-3) 
- (modified) clang/test/CIR/CodeGen/nullptr-init.cpp (+3-3) 
- (modified) clang/test/CIR/CodeGen/pointers.cpp (+6-6) 
- (modified) clang/test/CIR/CodeGen/struct.c (+17-17) 
- (modified) clang/test/CIR/CodeGen/struct.cpp (+2-2) 
- (modified) clang/test/CIR/CodeGen/switch.cpp (+7-7) 
- (modified) clang/test/CIR/CodeGen/switch_flat_op.cpp (+10-10) 
- (modified) clang/test/CIR/CodeGen/unary.cpp (+51-51) 
- (modified) clang/test/CIR/CodeGen/union.c (+24-24) 
- (modified) clang/test/CIR/CodeGen/union.cpp (+4-4) 
- (modified) clang/test/CIR/CodeGen/vector-ext.cpp (+70-70) 
- (modified) clang/test/CIR/CodeGen/vector.cpp (+70-70) 
- (modified) clang/test/CIR/CodeGenOpenACC/combined.cpp (+51-51) 
- (modified) clang/test/CIR/CodeGenOpenACC/data.c (+13-13) 
- (modified) clang/test/CIR/CodeGenOpenACC/init.c (+4-4) 
- (modified) clang/test/CIR/CodeGenOpenACC/kernels.c (+27-27) 
- (modified) clang/test/CIR/CodeGenOpenACC/loop.cpp (+22-22) 
- (modified) clang/test/CIR/CodeGenOpenACC/parallel.c (+29-29) 
- (modified) clang/test/CIR/CodeGenOpenACC/serial.c (+16-16) 
- (modified) clang/test/CIR/CodeGenOpenACC/set.c (+5-5) 
- (modified) clang/test/CIR/CodeGenOpenACC/shutdown.c (+4-4) 
- (modified) clang/test/CIR/CodeGenOpenACC/wait.c (+5-5) 
- (modified) clang/test/CIR/Lowering/array.cpp (+3-2) 
- (modified) clang/test/CIR/Lowering/local-vars.cpp (+4-3) 
- (modified) clang/test/CIR/Lowering/unary-expr-or-type-trait.cpp (+16-15) 


``````````diff
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 738f33bf36c9e..9de3a66755778 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -184,19 +184,9 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
                                     global.getSymName());
   }
 
-  cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr,
-                         bool isVolatile = false, uint64_t alignment = 0) {
-    mlir::IntegerAttr intAttr;
-    if (alignment)
-      intAttr = mlir::IntegerAttr::get(
-          mlir::IntegerType::get(ptr.getContext(), 64), alignment);
-
-    return create<cir::LoadOp>(loc, ptr);
-  }
-
-  cir::StoreOp createStore(mlir::Location loc, mlir::Value val,
-                           mlir::Value dst) {
-    return create<cir::StoreOp>(loc, val, dst);
+  cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst,
+                           mlir::IntegerAttr align = {}) {
+    return create<cir::StoreOp>(loc, val, dst, align);
   }
 
   cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy,
@@ -209,7 +199,12 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
                                clang::CharUnits alignment) {
     auto addr = createAlloca(loc, getPointerTo(type), type, {},
                              getSizeFromCharUnits(getContext(), alignment));
-    return createLoad(loc, addr);
+    mlir::IntegerAttr alignAttr;
+    uint64_t align = alignment.getQuantity();
+    if (align)
+      alignAttr = getI64IntegerAttr(align);
+
+    return create<cir::LoadOp>(loc, addr, /*isDeref=*/false, alignAttr);
   }
 
   cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base,
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 8267df92e3187..eaa4c9702137c 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -417,11 +417,15 @@ def LoadOp : CIR_Op<"load", [
   }];
 
   let arguments = (ins Arg<CIR_PointerType, "the address to load from",
-                           [MemRead]>:$addr, UnitAttr:$isDeref);
+                           [MemRead]>:$addr,
+                       UnitAttr:$isDeref,
+                       OptionalAttr<I64Attr>:$alignment
+                       );
   let results = (outs CIR_AnyType:$result);
 
   let assemblyFormat = [{
     (`deref` $isDeref^)?
+    (`align` `(` $alignment^ `)`)?
     $addr `:` qualified(type($addr)) `,` type($result) attr-dict
   }];
 
@@ -458,9 +462,11 @@ def StoreOp : CIR_Op<"store", [
 
   let arguments = (ins CIR_AnyType:$value,
                        Arg<CIR_PointerType, "the address to store the value",
-                           [MemWrite]>:$addr);
+                           [MemWrite]>:$addr,
+                           OptionalAttr<I64Attr>:$alignment);
 
   let assemblyFormat = [{
+    (`align` `(` $alignment^ `)`)?
     $value `,` $addr attr-dict `:` type($value) `,` qualified(type($addr))
   }];
 
@@ -1643,7 +1649,8 @@ def GlobalOp : CIR_Op<"global"> {
                        TypeAttr:$sym_type,
                        Arg<GlobalLinkageKind, "linkage type">:$linkage,
                        OptionalAttr<AnyAttr>:$initial_value,
-                       UnitAttr:$dsolocal);
+                       UnitAttr:$dsolocal,
+                       OptionalAttr<I64Attr>:$alignment);
 
   let assemblyFormat = [{
     $linkage
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index d4952da326ac0..fb205e9cd85d1 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -34,11 +34,14 @@ struct MissingFeatures {
   static bool opGlobalDSOLocal() { return false; }
   static bool opGlobalThreadLocal() { return false; }
   static bool opGlobalConstant() { return false; }
-  static bool opGlobalAlignment() { return false; }
   static bool opGlobalWeakRef() { return false; }
   static bool opGlobalLinkage() { return false; }
-  static bool opGlobalSetVisitibility() { return false; }
   static bool opGlobalUnnamedAddr() { return false; }
+  static bool opGlobalSection() { return false; }
+  static bool opGlobalVisibility() { return false; }
+  static bool opGlobalDLLImportExport() { return false; }
+  static bool opGlobalPartition() { return false; }
+  static bool opGlobalCIRGlobalValueInterface() { return false; }
 
   static bool supportIFuncAttr() { return false; }
   static bool supportVisibility() { return false; }
@@ -51,7 +54,6 @@ struct MissingFeatures {
   static bool opLoadStoreTbaa() { return false; }
   static bool opLoadStoreMemOrder() { return false; }
   static bool opLoadStoreVolatile() { return false; }
-  static bool opLoadStoreAlignment() { return false; }
   static bool opLoadStoreAtomic() { return false; }
   static bool opLoadStoreObjC() { return false; }
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 9c0968f144eef..5e56aa9e740e6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENBUILDER_H
 #define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENBUILDER_H
 
+#include "Address.h"
 #include "CIRGenTypeCache.h"
 #include "clang/CIR/MissingFeatures.h"
 
@@ -279,6 +280,26 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
     return create<cir::BinOp>(loc, cir::BinOpKind::Div, lhs, rhs);
   }
 
+  cir::LoadOp createLoad(mlir::Location loc, Address addr,
+                         bool isVolatile = false) {
+    mlir::IntegerAttr align;
+    uint64_t alignment = addr.getAlignment().getQuantity();
+    if (alignment)
+      align = getI64IntegerAttr(alignment);
+    return create<cir::LoadOp>(loc, addr.getPointer(), /*isDeref=*/false, align);
+  }
+
+  cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst,
+                           ::mlir::IntegerAttr align = {}) {
+    if (!align) {
+      uint64_t alignment = dst.getAlignment().getQuantity();
+      if (alignment)
+        align = mlir::IntegerAttr::get(mlir::IntegerType::get(getContext(), 64),
+                                       alignment);
+    }
+    return CIRBaseBuilderTy::createStore(loc, val, dst.getPointer(), align);
+  }
+
   /// Create a cir.ptr_stride operation to get access to an array element.
   /// \p idx is the index of the element to access, \p shouldDecay is true if
   /// the result should decay to a pointer to the element type.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index a8fecafe4a1f3..5424c6a8d6f3c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -209,10 +209,10 @@ void CIRGenFunction::emitStoreThroughLValue(RValue src, LValue dst,
       // Read/modify/write the vector, inserting the new element
       const mlir::Location loc = dst.getVectorPointer().getLoc();
       const mlir::Value vector =
-          builder.createLoad(loc, dst.getVectorAddress().getPointer());
+          builder.createLoad(loc, dst.getVectorAddress());
       const mlir::Value newVector = builder.create<cir::VecInsertOp>(
           loc, vector, src.getScalarVal(), dst.getVectorIdx());
-      builder.createStore(loc, newVector, dst.getVectorAddress().getPointer());
+      builder.createStore(loc, newVector, dst.getVectorAddress());
       return;
     }
 
@@ -301,7 +301,7 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,
   }
 
   assert(currSrcLoc && "must pass in source location");
-  builder.createStore(*currSrcLoc, value, addr.getPointer() /*, isVolatile*/);
+  builder.createStore(*currSrcLoc, value, addr /*, isVolatile*/);
 
   if (isNontemporal) {
     cgm.errorNYI(addr.getPointer().getLoc(), "emitStoreOfScalar nontemporal");
@@ -409,12 +409,10 @@ mlir::Value CIRGenFunction::emitLoadOfScalar(LValue lvalue,
   Address addr = lvalue.getAddress();
   mlir::Type eltTy = addr.getElementType();
 
-  mlir::Value ptr = addr.getPointer();
   if (mlir::isa<cir::VoidType>(eltTy))
     cgm.errorNYI(loc, "emitLoadOfScalar: void type");
 
-  mlir::Value loadOp = builder.CIRBaseBuilderTy::createLoad(
-      getLoc(loc), ptr, false /*isVolatile*/);
+  mlir::Value loadOp = builder.createLoad(getLoc(loc), addr);
 
   return loadOp;
 }
@@ -431,7 +429,7 @@ RValue CIRGenFunction::emitLoadOfLValue(LValue lv, SourceLocation loc) {
 
   if (lv.isVectorElt()) {
     const mlir::Value load =
-        builder.createLoad(getLoc(loc), lv.getVectorAddress().getPointer());
+        builder.createLoad(getLoc(loc), lv.getVectorAddress());
     return RValue::get(builder.create<cir::VecExtractOp>(getLoc(loc), load,
                                                          lv.getVectorIdx()));
   }
@@ -745,11 +743,12 @@ CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) {
 
 LValue CIRGenFunction::emitStringLiteralLValue(const StringLiteral *e) {
   cir::GlobalOp globalOp = cgm.getGlobalForStringLiteral(e);
-  assert(!cir::MissingFeatures::opGlobalAlignment());
+  assert(globalOp.getAlignment() && "expected alignment for string literal");
+  unsigned align = *(globalOp.getAlignment());
   mlir::Value addr =
       builder.createGetGlobal(getLoc(e->getSourceRange()), globalOp);
   return makeAddrLValue(
-      Address(addr, globalOp.getSymType(), CharUnits::fromQuantity(1)),
+      Address(addr, globalOp.getSymType(), CharUnits::fromQuantity(align)),
       e->getType(), AlignmentSource::Decl);
 }
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index e006a77c6e7d6..ea354845f449c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -163,7 +163,7 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
     // TODO(CIR): Replace this part later with cir::DoWhileOp
     for (unsigned i = numInitElements; i != numArrayElements; ++i) {
       cir::LoadOp currentElement =
-          builder.createLoad(loc, tmpAddr.getPointer());
+          builder.createLoad(loc, tmpAddr);
 
       // Emit the actual filler expression.
       const LValue elementLV = cgf.makeAddrLValue(
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index ce88e656a38e8..4335214d77b7d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -607,7 +607,7 @@ void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr,
   // respective address.
   // Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, false);
   const mlir::Value zeroValue = builder.getNullValue(convertType(ty), loc);
-  builder.createStore(loc, zeroValue, destPtr.getPointer());
+  builder.createStore(loc, zeroValue, destPtr);
 }
 
 } // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index fba8c07b6860d..60a3048f548e8 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -366,6 +366,39 @@ CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,
       CIRGenModule::createGlobalOp(*this, loc, mangledName, ty,
                                    /*insertPoint=*/entry.getOperation());
 
+  // Handle things which are present even on external declarations.
+  if (d) {
+    if (langOpts.OpenMP && !langOpts.OpenMPSimd)
+      errorNYI(d->getSourceRange(), "OpenMP target global variable");
+
+    gv.setAlignmentAttr(getSize(astContext.getDeclAlign(d)));
+    assert(!cir::MissingFeatures::opGlobalConstant());
+    assert(!cir::MissingFeatures::opGlobalLinkage());
+
+    if (d->getTLSKind())
+      errorNYI(d->getSourceRange(), "thread local global variable");
+
+    assert(!cir::MissingFeatures::opGlobalDLLImportExport());
+    assert(!cir::MissingFeatures::opGlobalPartition());
+    assert(!cir::MissingFeatures::setDSOLocal());
+
+    // If required by the ABI, treat declarations of static data members with
+    // inline initializers as definitions.
+    if (astContext.isMSStaticDataMemberInlineDefinition(d))
+      errorNYI(d->getSourceRange(), "MS static data member inline definition");
+
+    assert(!cir::MissingFeatures::opGlobalSection());
+    assert(!cir::MissingFeatures::opGlobalVisibility());
+
+    // Handle XCore specific ABI requirements.
+    if (getTriple().getArch() == llvm::Triple::xcore)
+      errorNYI(d->getSourceRange(), "XCore specific ABI requirements");
+
+    // We need to check for external const declarations with initializers here,
+    // but the 'isPublic()' part of the check uses the CIRGlobalValueInterface.
+    assert(!cir::MissingFeatures::opGlobalCIRGlobalValueInterface());
+  }
+
   return gv;
 }
 
@@ -775,7 +808,8 @@ CIRGenModule::getCIRLinkageVarDefinition(const VarDecl *vd, bool isConstant) {
 
 static cir::GlobalOp generateStringLiteral(mlir::Location loc,
                                            mlir::TypedAttr c, CIRGenModule &cgm,
-                                           StringRef globalName) {
+                                           StringRef globalName,
+                                           CharUnits alignment) {
   assert(!cir::MissingFeatures::addressSpace());
 
   // Create a global variable for this string
@@ -784,7 +818,7 @@ static cir::GlobalOp generateStringLiteral(mlir::Location loc,
       CIRGenModule::createGlobalOp(cgm, loc, globalName, c.getType());
 
   // Set up extra information and add to the module
-  assert(!cir::MissingFeatures::opGlobalAlignment());
+  gv.setAlignmentAttr(cgm.getSize(alignment));
   assert(!cir::MissingFeatures::opGlobalLinkage());
   assert(!cir::MissingFeatures::opGlobalThreadLocal());
   assert(!cir::MissingFeatures::opGlobalUnnamedAddr());
@@ -821,6 +855,9 @@ std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) {
 /// Return a pointer to a constant array for the given string literal.
 cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,
                                                       StringRef name) {
+  CharUnits alignment =
+      astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr);
+
   mlir::Attribute c = getConstantArrayFromStringLiteral(s);
 
   if (getLangOpts().WritableStrings) {
@@ -842,8 +879,8 @@ cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,
   std::string uniqueName = getUniqueGlobalName(name.str());
   mlir::Location loc = getLoc(s->getSourceRange());
   auto typedC = llvm::cast<mlir::TypedAttr>(c);
-  assert(!cir::MissingFeatures::opGlobalAlignment());
-  cir::GlobalOp gv = generateStringLiteral(loc, typedC, *this, uniqueName);
+  cir::GlobalOp gv =
+      generateStringLiteral(loc, typedC, *this, uniqueName, alignment);
   assert(!cir::MissingFeatures::opGlobalDSOLocal());
 
   assert(!cir::MissingFeatures::sanitizers());
@@ -918,7 +955,7 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
 void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
   // Recompute visibility when updating initializer.
   op.setInitialValueAttr(value);
-  assert(!cir::MissingFeatures::opGlobalSetVisitibility());
+  assert(!cir::MissingFeatures::opGlobalVisibility());
 }
 
 cir::FuncOp CIRGenModule::getAddrOfFunction(clang::GlobalDecl gd,
diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
index 763d2b087cc85..019a44636ce3c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
@@ -391,7 +391,8 @@ mlir::LogicalResult CIRGenFunction::emitReturnStmt(const ReturnStmt &s) {
     // If this function returns a reference, take the address of the
     // expression rather than the value.
     RValue result = emitReferenceBindingToExpr(rv);
-    builder.createStore(loc, result.getScalarVal(), *fnRetAlloca);
+    builder.CIRBaseBuilderTy::createStore(loc, result.getScalarVal(),
+                                          *fnRetAlloca);
   } else {
     mlir::Value value = nullptr;
     switch (CIRGenFunction::getEvaluationKind(rv->getType())) {
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 479d249516699..b402177a5ec18 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -353,6 +353,12 @@ uint64_t RecordType::getElementOffset(const ::mlir::DataLayout &dataLayout,
     offset += dataLayout.getTypeSize(ty);
   }
 
+  // Account for padding, if necessary, for the alignment of the field whose
+  // offset we are calculating.
+  const llvm::Align tyAlign = llvm::Align(
+      getPacked() ? 1 : dataLayout.getTypeABIAlignment(members[idx]));
+  offset = llvm::alignTo(offset, tyAlign);
+
   return offset;
 }
 
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 3d86f3d4deffb..fbc1ec735a216 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -728,8 +728,9 @@ mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
   const mlir::Type llvmTy = convertTypeForMemory(
       *getTypeConverter(), dataLayout, op.getResult().getType());
   assert(!cir::MissingFeatures::opLoadStoreMemOrder());
-  assert(!cir::MissingFeatures::opLoadStoreAlignment());
-  unsigned alignment = (unsigned)dataLayout.getTypeABIAlignment(llvmTy);
+  std::optional<size_t> opAlign = op.getAlignment();
+  unsigned alignment =
+      (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
 
   assert(!cir::MissingFeatures::lowerModeOptLevel());
 
@@ -753,10 +754,11 @@ mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
     cir::StoreOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
   assert(!cir::MissingFeatures::opLoadStoreMemOrder());
-  assert(!cir::MissingFeatures::opLoadStoreAlignment());
   const mlir::Type llvmTy =
       getTypeConverter()->convertType(op.getValue().getType());
-  unsigned alignment = (unsigned)dataLayout.getTypeABIAlignment(llvmTy);
+  std::optional<size_t> opAlign = op.getAlignment();
+  unsigned alignment =
+      (unsigned)opAlign.value_or(dataLayout.getTypeABIAlignment(llvmTy));
 
   assert(!cir::MissingFeatures::lowerModeOptLevel());
 
@@ -968,8 +970,7 @@ void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
   const bool isDsoLocal = true;
   assert(!cir::MissingFeatures::opGlobalThreadLocal());
   const bool isThreadLocal = false;
-  assert(!cir::MissingFeatures::opGlobalAlignment());
-  const uint64_t alignment = 0;
+  const uint64_t alignment = op.getAlignment().value_or(0);
   const mlir::LLVM::Linkage linkage = convertLinkage(op.getLinkage());
   const StringRef symbol = op.getSymName();
 
@@ -1024,8 +1025,7 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
   const bool isDsoLocal = true;
   assert(!cir::MissingFeatures::opGlobalThreadLocal());
   const bool isThreadLocal = false;
-  assert(!cir::MissingFeatures::opGlobalAlignment());
-  const uint64_t alignment = 0;
+  const uint64_t alignment = op.getAlignment().value_or(0);
   const mlir::LLVM::Linkage linkage = convertLinkage(op.getLinkage());
   const StringRef symbol = op.getSymName();
   SmallVector<mlir::NamedAttribute> attributes;
diff --git a/clang/test/CIR/CodeGen/align-load.c b/clang/test/CIR/CodeGen/align-load.c
new file mode 100644
index 0000000000000..06553a307f93a
--- /dev/null
+++ b/clang/test/CIR/CodeGen/align-load.c
@@ -0,0 +1,96 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %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
+// RUN: %clang_cc1 -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
+
+struct S {
+  char b;
+  short s;
+  int i;
+  float f;
+  double d;
+};
+
+void accessStruct(struct S u) {
+  u.b;
+  u.s;
+  u.i;
+  u.f;
+  u.d;
+}
+
+// CIR: cir.fun...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/141163


More information about the cfe-commits mailing list