Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ struct MissingFeatures {

// Misc
static bool abiArgInfo() { return false; }
static bool addAutoInitAnnotation() { return false; }
static bool addHeapAllocSiteMetadata() { return false; }
static bool aggEmitFinalDestCopyRValue() { return false; }
static bool aggValueSlot() { return false; }
Expand All @@ -198,6 +199,7 @@ struct MissingFeatures {
static bool aggValueSlotMayOverlap() { return false; }
static bool aggValueSlotVolatile() { return false; }
static bool alignCXXRecordDecl() { return false; }
static bool appleKext() { return false; }
static bool armComputeVolatileBitfields() { return false; }
static bool asmGoto() { return false; }
static bool asmInputOperands() { return false; }
Expand Down Expand Up @@ -243,6 +245,7 @@ struct MissingFeatures {
static bool deleteArray() { return false; }
static bool devirtualizeDestructor() { return false; }
static bool devirtualizeMemberFunction() { return false; }
static bool dtorCleanups() { return false; }
static bool ehCleanupFlags() { return false; }
static bool ehCleanupHasPrebranchedFallthrough() { return false; }
static bool ehCleanupScope() { return false; }
Expand Down Expand Up @@ -288,6 +291,7 @@ struct MissingFeatures {
static bool objCGC() { return false; }
static bool objCLifetime() { return false; }
static bool hlsl() { return false; }
static bool msvcBuiltins() { return false; }
static bool openCL() { return false; }
static bool openMP() { return false; }
static bool opTBAA() { return false; }
Expand All @@ -302,6 +306,10 @@ struct MissingFeatures {
static bool setNonGC() { return false; }
static bool setObjCGCLValueClass() { return false; }
static bool setTargetAttributes() { return false; }
static bool shouldCreateMemCpyFromGlobal() { return false; }
static bool shouldSplitConstantStore() { return false; }
static bool shouldUseBZeroPlusStoresToInitialize() { return false; }
static bool shouldUseMemSetToInitialize() { return false; }
static bool simplifyCleanupEntry() { return false; }
static bool sourceLanguageCases() { return false; }
static bool stackBase() { return false; }
Expand All @@ -313,16 +321,14 @@ struct MissingFeatures {
static bool thunks() { return false; }
static bool tryEmitAsConstant() { return false; }
static bool typeChecks() { return false; }
static bool weakRefReference() { return false; }
static bool writebacks() { return false; }
static bool appleKext() { return false; }
static bool dtorCleanups() { return false; }
static bool vaArgABILowering() { return false; }
static bool vectorConstants() { return false; }
static bool vlas() { return false; }
static bool vtableInitialization() { return false; }
static bool vtableEmitMetadata() { return false; }
static bool vtableRelativeLayout() { return false; }
static bool msvcBuiltins() { return false; }
static bool vaArgABILowering() { return false; }
static bool vlas() { return false; }
static bool weakRefReference() { return false; }
static bool writebacks() { return false; }

// Missing types
static bool dataMemberType() { return false; }
Expand Down
79 changes: 79 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,41 @@ CIRGenFunction::emitAutoVarAlloca(const VarDecl &d,

Address address = Address::invalid();
if (ty->isConstantSizeType()) {
// If this value is an array, struct, or vector with a statically
// determinable constant initializer, there are optimizations we can do.
//
// TODO: We should constant-evaluate the initializer of any variable,
// as long as it is initialized by a constant expression. Currently,
// isConstantInitializer produces wrong answers for structs with
// reference or bitfield members, and a few other cases, and checking
// for POD-ness protects us from some of these.
if (d.getInit() &&
(ty->isArrayType() || ty->isRecordType() || ty->isVectorType()) &&
(d.isConstexpr() ||
((ty.isPODType(getContext()) ||
getContext().getBaseElementType(ty)->isObjCObjectPointerType()) &&
d.getInit()->isConstantInitializer(getContext(), false)))) {

// If the variable's a const type, and it's neither an NRVO
// candidate nor a __block variable and has no mutable members,
// emit it as a global instead.
// Exception is if a variable is located in non-constant address space
// in OpenCL.
// TODO(cir): perhaps we don't need this at all at CIR since this can
// be done as part of lowering down to LLVM.
bool needsDtor =
d.needsDestruction(getContext()) == QualType::DK_cxx_destructor;
if ((!getContext().getLangOpts().OpenCL ||
ty.getAddressSpace() == LangAS::opencl_constant) &&
(cgm.getCodeGenOpts().MergeAllConstants && !nrvo &&
!d.isEscapingByref() &&
ty.isConstantStorage(getContext(), true, !needsDtor))) {
cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: type constant");
}
// Otherwise, tell the initialization code that we're in this case.
emission.isConstantAggregate = true;
}

// A normal fixed sized variable becomes an alloca in the entry block,
// unless:
// - it's an NRVO variable.
Expand Down Expand Up @@ -131,6 +166,47 @@ bool CIRGenFunction::isTrivialInitializer(const Expr *init) {
return false;
}

static void emitStoresForConstant(CIRGenModule &cgm, const VarDecl &d,
Address addr, bool isVolatile,
CIRGenBuilderTy &builder,
mlir::TypedAttr constant) {
mlir::Type ty = constant.getType();
cir::CIRDataLayout layout{cgm.getModule()};
uint64_t constantSize = layout.getTypeAllocSize(ty);
if (!constantSize)
return;
assert(!cir::MissingFeatures::addAutoInitAnnotation());
assert(!cir::MissingFeatures::vectorConstants());
assert(!cir::MissingFeatures::shouldUseBZeroPlusStoresToInitialize());
assert(!cir::MissingFeatures::shouldUseMemSetToInitialize());
assert(!cir::MissingFeatures::shouldSplitConstantStore());
assert(!cir::MissingFeatures::shouldCreateMemCpyFromGlobal());
// In CIR we want to emit a store for the whole thing, later lowering
// prepare to LLVM should unwrap this into the best policy (see asserts
// above).
//
// FIXME(cir): This is closer to memcpy behavior but less optimal, instead of
// copy from a global, we just create a cir.const out of it.

if (addr.getElementType() != ty)
addr = addr.withElementType(builder, ty);

// If the address is an alloca, set the init attribute.
// The address is usually and alloca, but there is at least one case where
// emitAutoVarInit is called from the OpenACC codegen with an address that
// is not an alloca.
auto allocaOp = addr.getDefiningOp<cir::AllocaOp>();
if (allocaOp)
allocaOp.setInitAttr(mlir::UnitAttr::get(&cgm.getMLIRContext()));

// There are cases where OpenACC codegen calls emitAutoVarInit with a
// temporary decl that doesn't have a source range set.
mlir::Location loc = builder.getUnknownLoc();
if (d.getSourceRange().isValid())
loc = cgm.getLoc(d.getSourceRange());
builder.createStore(loc, builder.getConstant(loc, constant), addr);
}

void CIRGenFunction::emitAutoVarInit(
const CIRGenFunction::AutoVarEmission &emission) {
assert(emission.variable && "emission was not valid!");
Expand Down Expand Up @@ -237,6 +313,9 @@ void CIRGenFunction::emitAutoVarInit(
return emitStoreThroughLValue(
RValue::get(builder.getConstant(initLoc, typedConstant)), lv);
}

emitStoresForConstant(cgm, d, addr, type.isVolatileQualified(), builder,
typedConstant);
}

void CIRGenFunction::emitAutoVarCleanups(
Expand Down
13 changes: 5 additions & 8 deletions clang/test/CIR/CodeGen/agg-expr-lvalue.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,13 @@ void test_string_array_in_array(void) {
}

// CIR-LABEL: cir.func{{.*}} @test_string_array_in_array
// CIR: cir.alloca !cir.array<!cir.array<!s8i x 6> x 2>, {{.*}}, ["matrix", init]
// CIR: cir.get_global
// CIR: cir.copy
// CIR: cir.get_global
// CIR: cir.copy
// CIR: %[[MATRIX:.*]] = cir.alloca !cir.array<!cir.array<!s8i x 6> x 2>, {{.*}}, ["matrix", init]
// CIR: %[[CONST:.*]] = cir.const #cir.const_array<[#cir.const_array<[#cir.int<104> : !s8i, #cir.int<101> : !s8i, #cir.int<108> : !s8i, #cir.int<108> : !s8i, #cir.int<111> : !s8i, #cir.int<0> : !s8i]> : !cir.array<!s8i x 6>, #cir.const_array<[#cir.int<119> : !s8i, #cir.int<111> : !s8i, #cir.int<114> : !s8i, #cir.int<108> : !s8i, #cir.int<100> : !s8i, #cir.int<0> : !s8i]> : !cir.array<!s8i x 6>]>
// CIR: cir.store{{.*}} %[[CONST]], %[[MATRIX]]

// LLVM-LABEL: define{{.*}} @test_string_array_in_array
// LLVM: alloca [2 x [6 x i8]]
// LLVM: call void @llvm.memcpy
// LLVM: call void @llvm.memcpy
// LLVM: %[[MATRIX:.*]] = alloca [2 x [6 x i8]]
// LLVM: store [2 x [6 x i8]] {{\[}}[6 x i8] c"hello\00", [6 x i8] c"world\00"], ptr %[[MATRIX]]

// OGCG-LABEL: define{{.*}} @test_string_array_in_array
// OGCG: alloca [2 x [6 x i8]]
Expand Down
Loading
Loading