Skip to content

Commit ea3c225

Browse files
authored
[CIR] Add alignment support for global, store, and load ops (llvm#141163)
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.
1 parent 1695e8b commit ea3c225

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1109
-821
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -184,19 +184,9 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
184184
global.getSymName());
185185
}
186186

187-
cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr,
188-
bool isVolatile = false, uint64_t alignment = 0) {
189-
mlir::IntegerAttr intAttr;
190-
if (alignment)
191-
intAttr = mlir::IntegerAttr::get(
192-
mlir::IntegerType::get(ptr.getContext(), 64), alignment);
193-
194-
return create<cir::LoadOp>(loc, ptr);
195-
}
196-
197-
cir::StoreOp createStore(mlir::Location loc, mlir::Value val,
198-
mlir::Value dst) {
199-
return create<cir::StoreOp>(loc, val, dst);
187+
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst,
188+
mlir::IntegerAttr align = {}) {
189+
return create<cir::StoreOp>(loc, val, dst, align);
200190
}
201191

202192
cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy,
@@ -209,7 +199,12 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
209199
clang::CharUnits alignment) {
210200
auto addr = createAlloca(loc, getPointerTo(type), type, {},
211201
getSizeFromCharUnits(getContext(), alignment));
212-
return createLoad(loc, addr);
202+
mlir::IntegerAttr alignAttr;
203+
uint64_t align = alignment.getQuantity();
204+
if (align)
205+
alignAttr = getI64IntegerAttr(align);
206+
207+
return create<cir::LoadOp>(loc, addr, /*isDeref=*/false, alignAttr);
213208
}
214209

215210
cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base,

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -417,11 +417,15 @@ def LoadOp : CIR_Op<"load", [
417417
}];
418418

419419
let arguments = (ins Arg<CIR_PointerType, "the address to load from",
420-
[MemRead]>:$addr, UnitAttr:$isDeref);
420+
[MemRead]>:$addr,
421+
UnitAttr:$isDeref,
422+
OptionalAttr<I64Attr>:$alignment
423+
);
421424
let results = (outs CIR_AnyType:$result);
422425

423426
let assemblyFormat = [{
424427
(`deref` $isDeref^)?
428+
(`align` `(` $alignment^ `)`)?
425429
$addr `:` qualified(type($addr)) `,` type($result) attr-dict
426430
}];
427431

@@ -458,9 +462,11 @@ def StoreOp : CIR_Op<"store", [
458462

459463
let arguments = (ins CIR_AnyType:$value,
460464
Arg<CIR_PointerType, "the address to store the value",
461-
[MemWrite]>:$addr);
465+
[MemWrite]>:$addr,
466+
OptionalAttr<I64Attr>:$alignment);
462467

463468
let assemblyFormat = [{
469+
(`align` `(` $alignment^ `)`)?
464470
$value `,` $addr attr-dict `:` type($value) `,` qualified(type($addr))
465471
}];
466472

@@ -1643,7 +1649,8 @@ def GlobalOp : CIR_Op<"global"> {
16431649
TypeAttr:$sym_type,
16441650
Arg<GlobalLinkageKind, "linkage type">:$linkage,
16451651
OptionalAttr<AnyAttr>:$initial_value,
1646-
UnitAttr:$dsolocal);
1652+
UnitAttr:$dsolocal,
1653+
OptionalAttr<I64Attr>:$alignment);
16471654

16481655
let assemblyFormat = [{
16491656
$linkage

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,14 @@ struct MissingFeatures {
3434
static bool opGlobalDSOLocal() { return false; }
3535
static bool opGlobalThreadLocal() { return false; }
3636
static bool opGlobalConstant() { return false; }
37-
static bool opGlobalAlignment() { return false; }
3837
static bool opGlobalWeakRef() { return false; }
3938
static bool opGlobalLinkage() { return false; }
40-
static bool opGlobalSetVisitibility() { return false; }
4139
static bool opGlobalUnnamedAddr() { return false; }
40+
static bool opGlobalSection() { return false; }
41+
static bool opGlobalVisibility() { return false; }
42+
static bool opGlobalDLLImportExport() { return false; }
43+
static bool opGlobalPartition() { return false; }
44+
static bool opGlobalCIRGlobalValueInterface() { return false; }
4245

4346
static bool supportIFuncAttr() { return false; }
4447
static bool supportVisibility() { return false; }
@@ -51,7 +54,6 @@ struct MissingFeatures {
5154
static bool opLoadStoreTbaa() { return false; }
5255
static bool opLoadStoreMemOrder() { return false; }
5356
static bool opLoadStoreVolatile() { return false; }
54-
static bool opLoadStoreAlignment() { return false; }
5557
static bool opLoadStoreAtomic() { return false; }
5658
static bool opLoadStoreObjC() { return false; }
5759

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENBUILDER_H
1010
#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENBUILDER_H
1111

12+
#include "Address.h"
1213
#include "CIRGenTypeCache.h"
1314
#include "clang/CIR/MissingFeatures.h"
1415

@@ -279,6 +280,27 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
279280
return create<cir::BinOp>(loc, cir::BinOpKind::Div, lhs, rhs);
280281
}
281282

283+
cir::LoadOp createLoad(mlir::Location loc, Address addr,
284+
bool isVolatile = false) {
285+
mlir::IntegerAttr align;
286+
uint64_t alignment = addr.getAlignment().getQuantity();
287+
if (alignment)
288+
align = getI64IntegerAttr(alignment);
289+
return create<cir::LoadOp>(loc, addr.getPointer(), /*isDeref=*/false,
290+
align);
291+
}
292+
293+
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst,
294+
::mlir::IntegerAttr align = {}) {
295+
if (!align) {
296+
uint64_t alignment = dst.getAlignment().getQuantity();
297+
if (alignment)
298+
align = mlir::IntegerAttr::get(mlir::IntegerType::get(getContext(), 64),
299+
alignment);
300+
}
301+
return CIRBaseBuilderTy::createStore(loc, val, dst.getPointer(), align);
302+
}
303+
282304
/// Create a cir.ptr_stride operation to get access to an array element.
283305
/// \p idx is the index of the element to access, \p shouldDecay is true if
284306
/// the result should decay to a pointer to the element type.

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,10 @@ void CIRGenFunction::emitStoreThroughLValue(RValue src, LValue dst,
209209
// Read/modify/write the vector, inserting the new element
210210
const mlir::Location loc = dst.getVectorPointer().getLoc();
211211
const mlir::Value vector =
212-
builder.createLoad(loc, dst.getVectorAddress().getPointer());
212+
builder.createLoad(loc, dst.getVectorAddress());
213213
const mlir::Value newVector = builder.create<cir::VecInsertOp>(
214214
loc, vector, src.getScalarVal(), dst.getVectorIdx());
215-
builder.createStore(loc, newVector, dst.getVectorAddress().getPointer());
215+
builder.createStore(loc, newVector, dst.getVectorAddress());
216216
return;
217217
}
218218

@@ -301,7 +301,7 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,
301301
}
302302

303303
assert(currSrcLoc && "must pass in source location");
304-
builder.createStore(*currSrcLoc, value, addr.getPointer() /*, isVolatile*/);
304+
builder.createStore(*currSrcLoc, value, addr /*, isVolatile*/);
305305

306306
if (isNontemporal) {
307307
cgm.errorNYI(addr.getPointer().getLoc(), "emitStoreOfScalar nontemporal");
@@ -409,12 +409,10 @@ mlir::Value CIRGenFunction::emitLoadOfScalar(LValue lvalue,
409409
Address addr = lvalue.getAddress();
410410
mlir::Type eltTy = addr.getElementType();
411411

412-
mlir::Value ptr = addr.getPointer();
413412
if (mlir::isa<cir::VoidType>(eltTy))
414413
cgm.errorNYI(loc, "emitLoadOfScalar: void type");
415414

416-
mlir::Value loadOp = builder.CIRBaseBuilderTy::createLoad(
417-
getLoc(loc), ptr, false /*isVolatile*/);
415+
mlir::Value loadOp = builder.createLoad(getLoc(loc), addr);
418416

419417
return loadOp;
420418
}
@@ -431,7 +429,7 @@ RValue CIRGenFunction::emitLoadOfLValue(LValue lv, SourceLocation loc) {
431429

432430
if (lv.isVectorElt()) {
433431
const mlir::Value load =
434-
builder.createLoad(getLoc(loc), lv.getVectorAddress().getPointer());
432+
builder.createLoad(getLoc(loc), lv.getVectorAddress());
435433
return RValue::get(builder.create<cir::VecExtractOp>(getLoc(loc), load,
436434
lv.getVectorIdx()));
437435
}
@@ -745,11 +743,12 @@ CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) {
745743

746744
LValue CIRGenFunction::emitStringLiteralLValue(const StringLiteral *e) {
747745
cir::GlobalOp globalOp = cgm.getGlobalForStringLiteral(e);
748-
assert(!cir::MissingFeatures::opGlobalAlignment());
746+
assert(globalOp.getAlignment() && "expected alignment for string literal");
747+
unsigned align = *(globalOp.getAlignment());
749748
mlir::Value addr =
750749
builder.createGetGlobal(getLoc(e->getSourceRange()), globalOp);
751750
return makeAddrLValue(
752-
Address(addr, globalOp.getSymType(), CharUnits::fromQuantity(1)),
751+
Address(addr, globalOp.getSymType(), CharUnits::fromQuantity(align)),
753752
e->getType(), AlignmentSource::Decl);
754753
}
755754

clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,7 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
162162

163163
// TODO(CIR): Replace this part later with cir::DoWhileOp
164164
for (unsigned i = numInitElements; i != numArrayElements; ++i) {
165-
cir::LoadOp currentElement =
166-
builder.createLoad(loc, tmpAddr.getPointer());
165+
cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr);
167166

168167
// Emit the actual filler expression.
169168
const LValue elementLV = cgf.makeAddrLValue(

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr,
607607
// respective address.
608608
// Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, false);
609609
const mlir::Value zeroValue = builder.getNullValue(convertType(ty), loc);
610-
builder.createStore(loc, zeroValue, destPtr.getPointer());
610+
builder.createStore(loc, zeroValue, destPtr);
611611
}
612612

613613
} // namespace clang::CIRGen

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,39 @@ CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,
366366
CIRGenModule::createGlobalOp(*this, loc, mangledName, ty,
367367
/*insertPoint=*/entry.getOperation());
368368

369+
// Handle things which are present even on external declarations.
370+
if (d) {
371+
if (langOpts.OpenMP && !langOpts.OpenMPSimd)
372+
errorNYI(d->getSourceRange(), "OpenMP target global variable");
373+
374+
gv.setAlignmentAttr(getSize(astContext.getDeclAlign(d)));
375+
assert(!cir::MissingFeatures::opGlobalConstant());
376+
assert(!cir::MissingFeatures::opGlobalLinkage());
377+
378+
if (d->getTLSKind())
379+
errorNYI(d->getSourceRange(), "thread local global variable");
380+
381+
assert(!cir::MissingFeatures::opGlobalDLLImportExport());
382+
assert(!cir::MissingFeatures::opGlobalPartition());
383+
assert(!cir::MissingFeatures::setDSOLocal());
384+
385+
// If required by the ABI, treat declarations of static data members with
386+
// inline initializers as definitions.
387+
if (astContext.isMSStaticDataMemberInlineDefinition(d))
388+
errorNYI(d->getSourceRange(), "MS static data member inline definition");
389+
390+
assert(!cir::MissingFeatures::opGlobalSection());
391+
assert(!cir::MissingFeatures::opGlobalVisibility());
392+
393+
// Handle XCore specific ABI requirements.
394+
if (getTriple().getArch() == llvm::Triple::xcore)
395+
errorNYI(d->getSourceRange(), "XCore specific ABI requirements");
396+
397+
// We need to check for external const declarations with initializers here,
398+
// but the 'isPublic()' part of the check uses the CIRGlobalValueInterface.
399+
assert(!cir::MissingFeatures::opGlobalCIRGlobalValueInterface());
400+
}
401+
369402
return gv;
370403
}
371404

@@ -775,7 +808,8 @@ CIRGenModule::getCIRLinkageVarDefinition(const VarDecl *vd, bool isConstant) {
775808

776809
static cir::GlobalOp generateStringLiteral(mlir::Location loc,
777810
mlir::TypedAttr c, CIRGenModule &cgm,
778-
StringRef globalName) {
811+
StringRef globalName,
812+
CharUnits alignment) {
779813
assert(!cir::MissingFeatures::addressSpace());
780814

781815
// Create a global variable for this string
@@ -784,7 +818,7 @@ static cir::GlobalOp generateStringLiteral(mlir::Location loc,
784818
CIRGenModule::createGlobalOp(cgm, loc, globalName, c.getType());
785819

786820
// Set up extra information and add to the module
787-
assert(!cir::MissingFeatures::opGlobalAlignment());
821+
gv.setAlignmentAttr(cgm.getSize(alignment));
788822
assert(!cir::MissingFeatures::opGlobalLinkage());
789823
assert(!cir::MissingFeatures::opGlobalThreadLocal());
790824
assert(!cir::MissingFeatures::opGlobalUnnamedAddr());
@@ -821,6 +855,9 @@ std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) {
821855
/// Return a pointer to a constant array for the given string literal.
822856
cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,
823857
StringRef name) {
858+
CharUnits alignment =
859+
astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr);
860+
824861
mlir::Attribute c = getConstantArrayFromStringLiteral(s);
825862

826863
if (getLangOpts().WritableStrings) {
@@ -842,8 +879,8 @@ cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,
842879
std::string uniqueName = getUniqueGlobalName(name.str());
843880
mlir::Location loc = getLoc(s->getSourceRange());
844881
auto typedC = llvm::cast<mlir::TypedAttr>(c);
845-
assert(!cir::MissingFeatures::opGlobalAlignment());
846-
cir::GlobalOp gv = generateStringLiteral(loc, typedC, *this, uniqueName);
882+
cir::GlobalOp gv =
883+
generateStringLiteral(loc, typedC, *this, uniqueName, alignment);
847884
assert(!cir::MissingFeatures::opGlobalDSOLocal());
848885

849886
assert(!cir::MissingFeatures::sanitizers());
@@ -918,7 +955,7 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
918955
void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
919956
// Recompute visibility when updating initializer.
920957
op.setInitialValueAttr(value);
921-
assert(!cir::MissingFeatures::opGlobalSetVisitibility());
958+
assert(!cir::MissingFeatures::opGlobalVisibility());
922959
}
923960

924961
cir::FuncOp CIRGenModule::getAddrOfFunction(clang::GlobalDecl gd,

clang/lib/CIR/CodeGen/CIRGenStmt.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,8 @@ mlir::LogicalResult CIRGenFunction::emitReturnStmt(const ReturnStmt &s) {
391391
// If this function returns a reference, take the address of the
392392
// expression rather than the value.
393393
RValue result = emitReferenceBindingToExpr(rv);
394-
builder.createStore(loc, result.getScalarVal(), *fnRetAlloca);
394+
builder.CIRBaseBuilderTy::createStore(loc, result.getScalarVal(),
395+
*fnRetAlloca);
395396
} else {
396397
mlir::Value value = nullptr;
397398
switch (CIRGenFunction::getEvaluationKind(rv->getType())) {

clang/lib/CIR/Dialect/IR/CIRTypes.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,12 @@ uint64_t RecordType::getElementOffset(const ::mlir::DataLayout &dataLayout,
353353
offset += dataLayout.getTypeSize(ty);
354354
}
355355

356+
// Account for padding, if necessary, for the alignment of the field whose
357+
// offset we are calculating.
358+
const llvm::Align tyAlign = llvm::Align(
359+
getPacked() ? 1 : dataLayout.getTypeABIAlignment(members[idx]));
360+
offset = llvm::alignTo(offset, tyAlign);
361+
356362
return offset;
357363
}
358364

0 commit comments

Comments
 (0)