From 1c92e3f6b4ef4daf48a75a0aa7c6c3db5e15e55f Mon Sep 17 00:00:00 2001 From: Andy Kaylor Date: Wed, 12 Feb 2025 02:42:14 -0800 Subject: [PATCH] [CIR][NFC] Refactor GlobalOpLowering to align with upstream (#1337) This change refactors the CIRToLLVMGlobalOpLowering handling to align with changes that were requested upstream. The upstream changes didn't entirely fit with the full incubator implementation but these changes fit the goals of the upstream refactoring into the current implementation. No observable changes are intended for this change. --- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 168 ++++++++---------- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 5 +- 2 files changed, 76 insertions(+), 97 deletions(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 5d8cf071927b..8cfee09104c4 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2307,8 +2307,9 @@ mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite( /// Replace CIR global with a region initialized LLVM global and update /// insertion point to the end of the initializer block. -void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp( - cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter) const { +void CIRToLLVMGlobalOpLowering::createRegionInitializedLLVMGlobalOp( + cir::GlobalOp op, mlir::Attribute attr, + mlir::ConversionPatternRewriter &rewriter) const { const auto llvmType = convertTypeForMemory(*getTypeConverter(), dataLayout, op.getSymType()); SmallVector attributes; @@ -2321,6 +2322,10 @@ void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp( /*comdat*/ mlir::SymbolRefAttr(), attributes); newGlobalOp.getRegion().push_back(new mlir::Block()); rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock()); + + rewriter.create( + op->getLoc(), + lowerCirAttrAsValue(op, attr, rewriter, typeConverter, dataLayout)); } mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( @@ -2350,109 +2355,82 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( attributes.push_back(rewriter.getNamedAttr("visibility_", visibility)); - // Check for missing funcionalities. - if (!init.has_value()) { - rewriter.replaceOpWithNewOp( - op, llvmType, isConst, linkage, symbol, mlir::Attribute(), - /*alignment*/ 0, - /*addrSpace*/ getGlobalOpTargetAddrSpace(rewriter, typeConverter, op), - /*dsoLocal*/ isDsoLocal, /*threadLocal*/ (bool)op.getTlsModelAttr(), - /*comdat*/ mlir::SymbolRefAttr(), attributes); - return mlir::success(); - } - - // Initializer is a constant array: convert it to a compatible llvm init. - if (auto constArr = mlir::dyn_cast(init.value())) { - if (auto attr = mlir::dyn_cast(constArr.getElts())) { - llvm::SmallString<256> literal(attr.getValue()); - if (constArr.getTrailingZerosNum()) - literal.append(constArr.getTrailingZerosNum(), '\0'); - init = rewriter.getStringAttr(literal); - } else if (auto attr = - mlir::dyn_cast(constArr.getElts())) { - // Failed to use a compact attribute as an initializer: - // initialize elements individually. - if (!(init = lowerConstArrayAttr(constArr, getTypeConverter()))) { - setupRegionInitializedLLVMGlobalOp(op, rewriter); - rewriter.create( - op->getLoc(), lowerCirAttrAsValue(op, constArr, rewriter, - typeConverter, dataLayout)); - return mlir::success(); + if (init.has_value()) { + if (mlir::isa(init.value())) { + // If a directly equivalent attribute is available, use it. + init = + llvm::TypeSwitch(init.value()) + .Case([&](cir::FPAttr attr) { + return rewriter.getFloatAttr(llvmType, attr.getValue()); + }) + .Case([&](cir::IntAttr attr) { + return rewriter.getIntegerAttr(llvmType, attr.getValue()); + }) + .Case([&](cir::BoolAttr attr) { + return rewriter.getBoolAttr(attr.getValue()); + }) + .Default([&](mlir::Attribute attr) { return mlir::Attribute(); }); + // If initRewriter returned a null attribute, init will have a value but + // the value will be null. If that happens, initRewriter didn't handle the + // attribute type. It probably needs to be added to + // GlobalInitAttrRewriter. + if (!init.value()) { + op.emitError() << "unsupported initializer '" << init.value() << "'"; + return mlir::failure(); } + } else if (mlir::isa(init.value())) { + // TODO(cir): once LLVM's dialect has proper equivalent attributes this + // should be updated. For now, we use a custom op to initialize globals + // to the appropriate value. + createRegionInitializedLLVMGlobalOp(op, init.value(), rewriter); + return mlir::success(); + } else if (auto constArr = + mlir::dyn_cast(init.value())) { + // Initializer is a constant array: convert it to a compatible llvm init. + if (auto attr = mlir::dyn_cast(constArr.getElts())) { + llvm::SmallString<256> literal(attr.getValue()); + if (constArr.getTrailingZerosNum()) + literal.append(constArr.getTrailingZerosNum(), '\0'); + init = rewriter.getStringAttr(literal); + } else if (auto attr = + mlir::dyn_cast(constArr.getElts())) { + // Failed to use a compact attribute as an initializer: + // initialize elements individually. + if (!(init = lowerConstArrayAttr(constArr, getTypeConverter()))) { + createRegionInitializedLLVMGlobalOp(op, constArr, rewriter); + return mlir::success(); + } + } else { + op.emitError() + << "unsupported lowering for #cir.const_array with value " + << constArr.getElts(); + return mlir::failure(); + } + } else if (auto dataMemberAttr = + mlir::dyn_cast(init.value())) { + assert(lowerMod && "lower module is not available"); + mlir::DataLayout layout(op->getParentOfType()); + mlir::TypedAttr abiValue = lowerMod->getCXXABI().lowerDataMemberConstant( + dataMemberAttr, layout, *typeConverter); + auto abiOp = mlir::cast(rewriter.clone(*op.getOperation())); + abiOp.setInitialValueAttr(abiValue); + abiOp.setSymType(abiValue.getType()); + rewriter.replaceOp(op, abiOp); + return mlir::success(); } else { - op.emitError() << "unsupported lowering for #cir.const_array with value " - << constArr.getElts(); + op.emitError() << "unsupported initializer '" << init.value() << "'"; return mlir::failure(); } - } else if (auto fltAttr = mlir::dyn_cast(init.value())) { - // Initializer is a constant floating-point number: convert to MLIR - // builtin constant. - init = rewriter.getFloatAttr(llvmType, fltAttr.getValue()); - } - // Initializer is a constant integer: convert to MLIR builtin constant. - else if (auto intAttr = mlir::dyn_cast(init.value())) { - init = rewriter.getIntegerAttr(llvmType, intAttr.getValue()); - } else if (auto boolAttr = mlir::dyn_cast(init.value())) { - init = rewriter.getBoolAttr(boolAttr.getValue()); - } else if (isa( - init.value())) { - // TODO(cir): once LLVM's dialect has proper equivalent attributes this - // should be updated. For now, we use a custom op to initialize globals - // to the appropriate value. - setupRegionInitializedLLVMGlobalOp(op, rewriter); - auto value = lowerCirAttrAsValue(op, init.value(), rewriter, typeConverter, - dataLayout); - rewriter.create(loc, value); - return mlir::success(); - } else if (auto dataMemberAttr = - mlir::dyn_cast(init.value())) { - assert(lowerMod && "lower module is not available"); - mlir::DataLayout layout(op->getParentOfType()); - mlir::TypedAttr abiValue = lowerMod->getCXXABI().lowerDataMemberConstant( - dataMemberAttr, layout, *typeConverter); - auto abiOp = mlir::cast(rewriter.clone(*op.getOperation())); - abiOp.setInitialValueAttr(abiValue); - abiOp.setSymType(abiValue.getType()); - rewriter.replaceOp(op, abiOp); - return mlir::success(); - } else if (const auto structAttr = - mlir::dyn_cast(init.value())) { - setupRegionInitializedLLVMGlobalOp(op, rewriter); - rewriter.create( - op->getLoc(), lowerCirAttrAsValue(op, structAttr, rewriter, - typeConverter, dataLayout)); - return mlir::success(); - } else if (auto attr = mlir::dyn_cast(init.value())) { - setupRegionInitializedLLVMGlobalOp(op, rewriter); - rewriter.create( - loc, - lowerCirAttrAsValue(op, attr, rewriter, typeConverter, dataLayout)); - return mlir::success(); - } else if (const auto vtableAttr = - mlir::dyn_cast(init.value())) { - setupRegionInitializedLLVMGlobalOp(op, rewriter); - rewriter.create( - op->getLoc(), lowerCirAttrAsValue(op, vtableAttr, rewriter, - typeConverter, dataLayout)); - return mlir::success(); - } else if (const auto typeinfoAttr = - mlir::dyn_cast(init.value())) { - setupRegionInitializedLLVMGlobalOp(op, rewriter); - rewriter.create( - op->getLoc(), lowerCirAttrAsValue(op, typeinfoAttr, rewriter, - typeConverter, dataLayout)); - return mlir::success(); - } else { - op.emitError() << "unsupported initializer '" << init.value() << "'"; - return mlir::failure(); } // Rewrite op. auto llvmGlobalOp = rewriter.replaceOpWithNewOp( - op, llvmType, isConst, linkage, symbol, init.value(), + op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()), /*alignment*/ op.getAlignment().value_or(0), /*addrSpace*/ getGlobalOpTargetAddrSpace(rewriter, typeConverter, op), - /*dsoLocal*/ false, /*threadLocal*/ (bool)op.getTlsModelAttr(), + /*dsoLocal*/ isDsoLocal, /*threadLocal*/ (bool)op.getTlsModelAttr(), /*comdat*/ mlir::SymbolRefAttr(), attributes); auto mod = op->getParentOfType(); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index 629d148427fd..7b668dea43f5 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -589,8 +589,9 @@ class CIRToLLVMGlobalOpLowering mlir::ConversionPatternRewriter &) const override; private: - void setupRegionInitializedLLVMGlobalOp( - cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter) const; + void createRegionInitializedLLVMGlobalOp( + cir::GlobalOp op, mlir::Attribute attr, + mlir::ConversionPatternRewriter &rewriter) const; mutable mlir::LLVM::ComdatOp comdatOp = nullptr; static void addComdat(mlir::LLVM::GlobalOp &op,