================
@@ -1250,6 +1254,236 @@ getSafeRepackAttrs(Fortran::lower::AbstractConverter
&converter) {
return attrs.empty() ? mlir::ArrayAttr{} : builder.getArrayAttr(attrs);
}
+//===----------------------------------------------------------------------===//
+// -finit-local= helpers
+//===----------------------------------------------------------------------===//
+
+/// Returns true when \p var is an automatic local variable eligible for
+/// -finit-local= initialization. Excluded: variables without a symbol,
+/// globals, dummy arguments, SAVE'd vars, ALLOCATABLE/POINTER, vars in
+/// an EQUIVALENCE set, and vars with explicit or default initialization.
+static bool shouldInitLocal(const Fortran::lower::pft::Variable &var) {
+ if (!var.hasSymbol() || var.isGlobal())
+ return false;
+ const Fortran::semantics::Symbol &sym = var.getSymbol();
+ if (Fortran::semantics::IsDummy(sym))
+ return false;
+ if (Fortran::semantics::IsSaved(sym))
+ return false;
+ if (Fortran::semantics::IsAllocatableOrPointer(sym))
+ return false;
+ if (Fortran::lower::hasDefaultInitialization(sym))
+ return false;
+ if (const auto *obj =
+ sym.detailsIf<Fortran::semantics::ObjectEntityDetails>())
+ if (obj->init())
+ return false;
+ if (Fortran::semantics::FindEquivalenceSet(sym))
+ return false;
+ return true;
+}
+
+/// Build a constant whose every byte equals \p bytePat.
+/// FP types: bitcast from an integer splat. Complex: apply to both parts.
+/// Character: falls back to fir.zero_bits (see TODO). Derived types are
+/// handled by the caller before this function is reached.
+static mlir::Value genByteSplatInit(fir::FirOpBuilder &builder,
+ mlir::Location loc, mlir::Type ty,
+ uint8_t bytePat) {
+ mlir::Type eleTy = fir::unwrapSequenceType(ty);
+
+ // Build an integer constant of the given bit width from a byte splat.
+ auto makeIntCst = [&](unsigned bits) -> mlir::Value {
+ llvm::APInt byteVal(8, bytePat);
+ llvm::APInt splat = llvm::APInt::getSplat(bits, byteVal);
+ mlir::Type intTy = builder.getIntegerType(bits);
+ return mlir::arith::ConstantOp::create(
+ builder, loc, intTy, builder.getIntegerAttr(intTy, splat));
+ };
+
+ if (auto fpTy = mlir::dyn_cast<mlir::FloatType>(eleTy)) {
+ unsigned bits = fpTy.getWidth();
+ mlir::Value intCst = makeIntCst(bits);
+ return mlir::arith::BitcastOp::create(builder, loc, fpTy, intCst);
+ }
+ if (auto intTy = mlir::dyn_cast<mlir::IntegerType>(eleTy)) {
+ return makeIntCst(intTy.getWidth());
+ }
+ // Complex: apply the byte pattern to each (real, imag) part.
+ if (auto cplxTy = mlir::dyn_cast<mlir::ComplexType>(eleTy)) {
+ mlir::Type partTy = cplxTy.getElementType();
+ mlir::Value partVal = genByteSplatInit(builder, loc, partTy, bytePat);
+ return mlir::complex::CreateOp::create(builder, loc, cplxTy, partVal,
+ partVal);
+ }
+ // TODO: CHARACTER falls back to zero; a future improvement should fill each
+ // storage unit with the byte pattern.
+ return fir::ZeroOp::create(builder, loc, eleTy);
----------------
MattPD wrote:
The implementation and executable test now cover higher-kind CHARACTER.
The HLFIR checks still do not require their constants to control the dataflow.
All three FileCheck runs pass when the loops use shorter bounds or the runtime
multiplication uses a factor of 1. The constants can remain unused: 5, 7, and 2.
Could the checks capture these constants and require each one as the
corresponding loop bound or runtime multiplication factor?
https://github.com/llvm/llvm-project/pull/216164
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits