@@ -50,6 +50,41 @@ CIRGenFunction::emitAutoVarAlloca(const VarDecl &d,
5050
5151 Address address = Address::invalid ();
5252 if (ty->isConstantSizeType ()) {
53+ // If this value is an array, struct, or vector with a statically
54+ // determinable constant initializer, there are optimizations we can do.
55+ //
56+ // TODO: We should constant-evaluate the initializer of any variable,
57+ // as long as it is initialized by a constant expression. Currently,
58+ // isConstantInitializer produces wrong answers for structs with
59+ // reference or bitfield members, and a few other cases, and checking
60+ // for POD-ness protects us from some of these.
61+ if (d.getInit () &&
62+ (ty->isArrayType () || ty->isRecordType () || ty->isVectorType ()) &&
63+ (d.isConstexpr () ||
64+ ((ty.isPODType (getContext ()) ||
65+ getContext ().getBaseElementType (ty)->isObjCObjectPointerType ()) &&
66+ d.getInit ()->isConstantInitializer (getContext (), false )))) {
67+
68+ // If the variable's a const type, and it's neither an NRVO
69+ // candidate nor a __block variable and has no mutable members,
70+ // emit it as a global instead.
71+ // Exception is if a variable is located in non-constant address space
72+ // in OpenCL.
73+ // TODO(cir): perhaps we don't need this at all at CIR since this can
74+ // be done as part of lowering down to LLVM.
75+ bool needsDtor =
76+ d.needsDestruction (getContext ()) == QualType::DK_cxx_destructor;
77+ if ((!getContext ().getLangOpts ().OpenCL ||
78+ ty.getAddressSpace () == LangAS::opencl_constant) &&
79+ (cgm.getCodeGenOpts ().MergeAllConstants && !nrvo &&
80+ !d.isEscapingByref () &&
81+ ty.isConstantStorage (getContext (), true , !needsDtor))) {
82+ cgm.errorNYI (d.getSourceRange (), " emitAutoVarAlloca: type constant" );
83+ }
84+ // Otherwise, tell the initialization code that we're in this case.
85+ emission.isConstantAggregate = true ;
86+ }
87+
5388 // A normal fixed sized variable becomes an alloca in the entry block,
5489 // unless:
5590 // - it's an NRVO variable.
@@ -131,6 +166,47 @@ bool CIRGenFunction::isTrivialInitializer(const Expr *init) {
131166 return false ;
132167}
133168
169+ static void emitStoresForConstant (CIRGenModule &cgm, const VarDecl &d,
170+ Address addr, bool isVolatile,
171+ CIRGenBuilderTy &builder,
172+ mlir::TypedAttr constant) {
173+ mlir::Type ty = constant.getType ();
174+ cir::CIRDataLayout layout{cgm.getModule ()};
175+ uint64_t constantSize = layout.getTypeAllocSize (ty);
176+ if (!constantSize)
177+ return ;
178+ assert (!cir::MissingFeatures::addAutoInitAnnotation ());
179+ assert (!cir::MissingFeatures::vectorConstants ());
180+ assert (!cir::MissingFeatures::shouldUseBZeroPlusStoresToInitialize ());
181+ assert (!cir::MissingFeatures::shouldUseMemSetToInitialize ());
182+ assert (!cir::MissingFeatures::shouldSplitConstantStore ());
183+ assert (!cir::MissingFeatures::shouldCreateMemCpyFromGlobal ());
184+ // In CIR we want to emit a store for the whole thing, later lowering
185+ // prepare to LLVM should unwrap this into the best policy (see asserts
186+ // above).
187+ //
188+ // FIXME(cir): This is closer to memcpy behavior but less optimal, instead of
189+ // copy from a global, we just create a cir.const out of it.
190+
191+ if (addr.getElementType () != ty)
192+ addr = addr.withElementType (builder, ty);
193+
194+ // If the address is an alloca, set the init attribute.
195+ // The address is usually and alloca, but there is at least one case where
196+ // emitAutoVarInit is called from the OpenACC codegen with an address that
197+ // is not an alloca.
198+ auto allocaOp = addr.getDefiningOp <cir::AllocaOp>();
199+ if (allocaOp)
200+ allocaOp.setInitAttr (mlir::UnitAttr::get (&cgm.getMLIRContext ()));
201+
202+ // There are cases where OpenACC codegen calls emitAutoVarInit with a
203+ // temporary decl that doesn't have a source range set.
204+ mlir::Location loc = builder.getUnknownLoc ();
205+ if (d.getSourceRange ().isValid ())
206+ loc = cgm.getLoc (d.getSourceRange ());
207+ builder.createStore (loc, builder.getConstant (loc, constant), addr);
208+ }
209+
134210void CIRGenFunction::emitAutoVarInit (
135211 const CIRGenFunction::AutoVarEmission &emission) {
136212 assert (emission.variable && " emission was not valid!" );
@@ -237,6 +313,9 @@ void CIRGenFunction::emitAutoVarInit(
237313 return emitStoreThroughLValue (
238314 RValue::get (builder.getConstant (initLoc, typedConstant)), lv);
239315 }
316+
317+ emitStoresForConstant (cgm, d, addr, type.isVolatileQualified (), builder,
318+ typedConstant);
240319}
241320
242321void CIRGenFunction::emitAutoVarCleanups (
0 commit comments