-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[CIR] Add support for __builtin_alloca #157116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-clang Author: Morris Hafner (mmha) ChangesThis patch adds support for the alloca builtin and extends AllocaOp with a dynamic size argument. Full diff: https://github.com/llvm/llvm-project/pull/157116.diff 8 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 8dc4ca2f9c4e1..a3f167e3cde2c 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -221,6 +221,22 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value));
}
+ mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
+ mlir::Type type, llvm::StringRef name,
+ mlir::IntegerAttr alignment,
+ mlir::Value dynAllocSize) {
+ return cir::AllocaOp::create(*this, loc, addrType, type, name, alignment,
+ dynAllocSize);
+ }
+
+ mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
+ mlir::Type type, llvm::StringRef name,
+ clang::CharUnits alignment,
+ mlir::Value dynAllocSize) {
+ mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
+ return createAlloca(loc, addrType, type, name, alignmentAttr, dynAllocSize);
+ }
+
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
mlir::Type type, llvm::StringRef name,
mlir::IntegerAttr alignment) {
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 4592078af966b..63aea2c404b54 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -341,6 +341,11 @@ def CIR_AllocaOp : CIR_Op<"alloca", [
The presence of the `const` attribute indicates that the local variable is
declared with C/C++ `const` keyword.
+ The `dynAllocSize` specifies the size to dynamically allocate on the stack
+ and ignores the allocation size based on the original type. This is useful
+ when handling VLAs or the `alloca` builtin and is omitted when declaring
+ regular local variables.
+
The result type is a pointer to the input's type.
Example:
@@ -356,6 +361,7 @@ def CIR_AllocaOp : CIR_Op<"alloca", [
}];
let arguments = (ins
+ Optional<CIR_AnyFundamentalIntType>:$dynAllocSize,
TypeAttr:$allocaType,
StrAttr:$name,
UnitAttr:$init,
@@ -372,16 +378,29 @@ def CIR_AllocaOp : CIR_Op<"alloca", [
OpBuilder<(ins "mlir::Type":$addr,
"mlir::Type":$allocaType,
"llvm::StringRef":$name,
- "mlir::IntegerAttr":$alignment)>
+ "mlir::IntegerAttr":$alignment)>,
+
+ OpBuilder<(ins "mlir::Type":$addr,
+ "mlir::Type":$allocaType,
+ "llvm::StringRef":$name,
+ "mlir::IntegerAttr":$alignment,
+ "mlir::Value":$dynAllocSize),
+ [{
+ if (dynAllocSize)
+ $_state.addOperands(dynAllocSize);
+ build($_builder, $_state, addr, allocaType, name, alignment);
+ }]>
];
let extraClassDeclaration = [{
// Whether the alloca input type is a pointer.
bool isPointerType() { return ::mlir::isa<::cir::PointerType>(getAllocaType()); }
+ bool isDynamic() { return (bool)getDynAllocSize(); }
}];
let assemblyFormat = [{
$allocaType `,` qualified(type($addr)) `,`
+ ($dynAllocSize^ `:` type($dynAllocSize) `,`)?
`[` $name
(`,` `init` $init^)?
(`,` `const` $constant^)?
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 948e3feca2bb5..1e64278d118b5 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -62,7 +62,6 @@ struct MissingFeatures {
static bool opAllocaEscapeByReference() { return false; }
static bool opAllocaReference() { return false; }
static bool opAllocaAnnotations() { return false; }
- static bool opAllocaDynAllocSize() { return false; }
static bool opAllocaCaptureByInit() { return false; }
// FuncOp handling
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index b68e91f64dc84..ddd95466dc1d0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -149,6 +149,57 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
emitVAEnd(emitVAListRef(e->getArg(0)).getPointer());
return {};
+ case Builtin::BIalloca:
+ case Builtin::BI_alloca:
+ case Builtin::BI__builtin_alloca_uninitialized:
+ case Builtin::BI__builtin_alloca: {
+ // Get alloca size input
+ mlir::Value size = emitScalarExpr(e->getArg(0));
+
+ // The alignment of the alloca should correspond to __BIGGEST_ALIGNMENT__.
+ const TargetInfo &TI = getContext().getTargetInfo();
+ const CharUnits SuitableAlignmentInBytes =
+ getContext().toCharUnitsFromBits(TI.getSuitableAlign());
+
+ // Emit the alloca op with type `u8 *` to match the semantics of
+ // `llvm.alloca`. We later bitcast the type to `void *` to match the
+ // semantics of C/C++
+ // FIXME(cir): It may make sense to allow AllocaOp of type `u8` to return a
+ // pointer of type `void *`. This will require a change to the allocaOp
+ // verifier.
+ auto allocaAddr = builder.createAlloca(
+ getLoc(e->getSourceRange()), builder.getUInt8PtrTy(),
+ builder.getUInt8Ty(), "bi_alloca", SuitableAlignmentInBytes, size);
+
+ // Initialize the allocated buffer if required.
+ if (builtinID != Builtin::BI__builtin_alloca_uninitialized) {
+ // Initialize the alloca with the given size and alignment according to
+ // the lang opts. Only the trivial non-initialization is supported for
+ // now.
+
+ switch (getLangOpts().getTrivialAutoVarInit()) {
+ case LangOptions::TrivialAutoVarInitKind::Uninitialized:
+ // Nothing to initialize.
+ break;
+ case LangOptions::TrivialAutoVarInitKind::Zero:
+ case LangOptions::TrivialAutoVarInitKind::Pattern:
+ cgm.errorNYI("trivial auto var init");
+ break;
+ }
+ }
+
+ // An alloca will always return a pointer to the alloca (stack) address
+ // space. This address space need not be the same as the AST / Language
+ // default (e.g. in C / C++ auto vars are in the generic address space). At
+ // the AST level this is handled within CreateTempAlloca et al., but for the
+ // builtin / dynamic alloca we have to handle it here.
+ assert(!cir::MissingFeatures::addressSpace());
+
+ // Bitcast the alloca to the expected type.
+ return RValue::get(
+ builder.createBitcast(allocaAddr, builder.getVoidPtrTy()));
+ }
+
case Builtin::BIfabs:
case Builtin::BIfabsf:
case Builtin::BIfabsl:
diff --git a/clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp b/clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp
index 4e0a041d26ce1..72bbf08c79b16 100644
--- a/clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp
@@ -42,7 +42,8 @@ static void process(mlir::ModuleOp mod, cir::FuncOp func) {
if (alloca->getBlock() == &entryBlock)
return;
// Don't hoist allocas with dynamic alloca size.
- assert(!cir::MissingFeatures::opAllocaDynAllocSize());
+ if (alloca.getDynAllocSize())
+ return;
// Hoist allocas into the entry block.
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index ee9f58c829ca9..8e8cd2a63dcd5 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1053,9 +1053,12 @@ mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
cir::AllocaOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
- assert(!cir::MissingFeatures::opAllocaDynAllocSize());
- mlir::Value size = rewriter.create<mlir::LLVM::ConstantOp>(
- op.getLoc(), typeConverter->convertType(rewriter.getIndexType()), 1);
+ mlir::Value size =
+ op.isDynamic() ? adaptor.getDynAllocSize()
+ : rewriter.create<mlir::LLVM::ConstantOp>(
+ op.getLoc(),
+ typeConverter->convertType(rewriter.getIndexType()),
+ rewriter.getIntegerAttr(rewriter.getIndexType(), 1));
mlir::Type elementTy =
convertTypeForMemory(*getTypeConverter(), dataLayout, op.getAllocaType());
mlir::Type resultTy =
diff --git a/clang/test/CIR/CodeGen/builtin_call.cpp b/clang/test/CIR/CodeGen/builtin_call.cpp
index 09be7937a4330..d416841c5d6fe 100644
--- a/clang/test/CIR/CodeGen/builtin_call.cpp
+++ b/clang/test/CIR/CodeGen/builtin_call.cpp
@@ -258,3 +258,13 @@ void trap2() {
// LLVM: {{.+}}:
// LLVM-NEXT: call void @_Z2f1v()
// LLVM: }
+
+void *test_alloca(unsigned long n) {
+ return __builtin_alloca(n);
+}
+
+// CIR-LABEL: @_Z11test_allocam(
+// CIR: %{{.+}} = cir.alloca !u8i, !cir.ptr<!u8i>, %{{.+}} : !u64i, ["bi_alloca"]
+
+// LLVM-LABEL: @_Z11test_allocam(
+// LLVM: alloca i8, i64 %{{.+}}
diff --git a/clang/test/CIR/IR/alloca.cir b/clang/test/CIR/IR/alloca.cir
new file mode 100644
index 0000000000000..12f7e6ac6a914
--- /dev/null
+++ b/clang/test/CIR/IR/alloca.cir
@@ -0,0 +1,32 @@
+
+// RUN: cir-opt %s | FileCheck %s
+
+!u64i = !cir.int<u, 64>
+!u8i = !cir.int<u, 8>
+!void = !cir.void
+module {
+ cir.func dso_local @_Z11test_allocam(%arg0: !u64i) -> !cir.ptr<!void> {
+ %0 = cir.alloca !u64i, !cir.ptr<!u64i>, ["n", init] {alignment = 8 : i64}
+ %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__retval"] {alignment = 8 : i64}
+ cir.store %arg0, %0 : !u64i, !cir.ptr<!u64i>
+ %2 = cir.load align(8) %0 : !cir.ptr<!u64i>, !u64i
+ // Dynamically sized alloca
+ %3 = cir.alloca !u8i, !cir.ptr<!u8i>, %2 : !u64i, ["bi_alloca"] {alignment = 16 : i64}
+ %4 = cir.cast(bitcast, %3 : !cir.ptr<!u8i>), !cir.ptr<!void>
+ cir.store %4, %1 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+ %5 = cir.load %1 : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+ cir.return %5 : !cir.ptr<!void>
+ }
+
+ // CHECK: cir.func dso_local @_Z11test_allocam(%arg0: !u64i) -> !cir.ptr<!void> {
+ // CHECK: %0 = cir.alloca !u64i, !cir.ptr<!u64i>, ["n", init] {alignment = 8 : i64}
+ // CHECK: %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__retval"] {alignment = 8 : i64}
+ // CHECK: cir.store %arg0, %0 : !u64i, !cir.ptr<!u64i>
+ // CHECK: %2 = cir.load align(8) %0 : !cir.ptr<!u64i>, !u64i
+ // CHECK: %3 = cir.alloca !u8i, !cir.ptr<!u8i>, %2 : !u64i, ["bi_alloca"] {alignment = 16 : i64}
+ // CHECK: %4 = cir.cast(bitcast, %3 : !cir.ptr<!u8i>), !cir.ptr<!void>
+ // CHECK: cir.store %4, %1 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+ // CHECK: %5 = cir.load %1 : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+ // CHECK: cir.return %5 : !cir.ptr<!void>
+ // CHECK: }
+}
|
|
@llvm/pr-subscribers-clangir Author: Morris Hafner (mmha) ChangesThis patch adds support for the alloca builtin and extends AllocaOp with a dynamic size argument. Full diff: https://github.com/llvm/llvm-project/pull/157116.diff 8 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 8dc4ca2f9c4e1..a3f167e3cde2c 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -221,6 +221,22 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value));
}
+ mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
+ mlir::Type type, llvm::StringRef name,
+ mlir::IntegerAttr alignment,
+ mlir::Value dynAllocSize) {
+ return cir::AllocaOp::create(*this, loc, addrType, type, name, alignment,
+ dynAllocSize);
+ }
+
+ mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
+ mlir::Type type, llvm::StringRef name,
+ clang::CharUnits alignment,
+ mlir::Value dynAllocSize) {
+ mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
+ return createAlloca(loc, addrType, type, name, alignmentAttr, dynAllocSize);
+ }
+
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
mlir::Type type, llvm::StringRef name,
mlir::IntegerAttr alignment) {
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 4592078af966b..63aea2c404b54 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -341,6 +341,11 @@ def CIR_AllocaOp : CIR_Op<"alloca", [
The presence of the `const` attribute indicates that the local variable is
declared with C/C++ `const` keyword.
+ The `dynAllocSize` specifies the size to dynamically allocate on the stack
+ and ignores the allocation size based on the original type. This is useful
+ when handling VLAs or the `alloca` builtin and is omitted when declaring
+ regular local variables.
+
The result type is a pointer to the input's type.
Example:
@@ -356,6 +361,7 @@ def CIR_AllocaOp : CIR_Op<"alloca", [
}];
let arguments = (ins
+ Optional<CIR_AnyFundamentalIntType>:$dynAllocSize,
TypeAttr:$allocaType,
StrAttr:$name,
UnitAttr:$init,
@@ -372,16 +378,29 @@ def CIR_AllocaOp : CIR_Op<"alloca", [
OpBuilder<(ins "mlir::Type":$addr,
"mlir::Type":$allocaType,
"llvm::StringRef":$name,
- "mlir::IntegerAttr":$alignment)>
+ "mlir::IntegerAttr":$alignment)>,
+
+ OpBuilder<(ins "mlir::Type":$addr,
+ "mlir::Type":$allocaType,
+ "llvm::StringRef":$name,
+ "mlir::IntegerAttr":$alignment,
+ "mlir::Value":$dynAllocSize),
+ [{
+ if (dynAllocSize)
+ $_state.addOperands(dynAllocSize);
+ build($_builder, $_state, addr, allocaType, name, alignment);
+ }]>
];
let extraClassDeclaration = [{
// Whether the alloca input type is a pointer.
bool isPointerType() { return ::mlir::isa<::cir::PointerType>(getAllocaType()); }
+ bool isDynamic() { return (bool)getDynAllocSize(); }
}];
let assemblyFormat = [{
$allocaType `,` qualified(type($addr)) `,`
+ ($dynAllocSize^ `:` type($dynAllocSize) `,`)?
`[` $name
(`,` `init` $init^)?
(`,` `const` $constant^)?
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 948e3feca2bb5..1e64278d118b5 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -62,7 +62,6 @@ struct MissingFeatures {
static bool opAllocaEscapeByReference() { return false; }
static bool opAllocaReference() { return false; }
static bool opAllocaAnnotations() { return false; }
- static bool opAllocaDynAllocSize() { return false; }
static bool opAllocaCaptureByInit() { return false; }
// FuncOp handling
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index b68e91f64dc84..ddd95466dc1d0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -149,6 +149,57 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
emitVAEnd(emitVAListRef(e->getArg(0)).getPointer());
return {};
+ case Builtin::BIalloca:
+ case Builtin::BI_alloca:
+ case Builtin::BI__builtin_alloca_uninitialized:
+ case Builtin::BI__builtin_alloca: {
+ // Get alloca size input
+ mlir::Value size = emitScalarExpr(e->getArg(0));
+
+ // The alignment of the alloca should correspond to __BIGGEST_ALIGNMENT__.
+ const TargetInfo &TI = getContext().getTargetInfo();
+ const CharUnits SuitableAlignmentInBytes =
+ getContext().toCharUnitsFromBits(TI.getSuitableAlign());
+
+ // Emit the alloca op with type `u8 *` to match the semantics of
+ // `llvm.alloca`. We later bitcast the type to `void *` to match the
+ // semantics of C/C++
+ // FIXME(cir): It may make sense to allow AllocaOp of type `u8` to return a
+ // pointer of type `void *`. This will require a change to the allocaOp
+ // verifier.
+ auto allocaAddr = builder.createAlloca(
+ getLoc(e->getSourceRange()), builder.getUInt8PtrTy(),
+ builder.getUInt8Ty(), "bi_alloca", SuitableAlignmentInBytes, size);
+
+ // Initialize the allocated buffer if required.
+ if (builtinID != Builtin::BI__builtin_alloca_uninitialized) {
+ // Initialize the alloca with the given size and alignment according to
+ // the lang opts. Only the trivial non-initialization is supported for
+ // now.
+
+ switch (getLangOpts().getTrivialAutoVarInit()) {
+ case LangOptions::TrivialAutoVarInitKind::Uninitialized:
+ // Nothing to initialize.
+ break;
+ case LangOptions::TrivialAutoVarInitKind::Zero:
+ case LangOptions::TrivialAutoVarInitKind::Pattern:
+ cgm.errorNYI("trivial auto var init");
+ break;
+ }
+ }
+
+ // An alloca will always return a pointer to the alloca (stack) address
+ // space. This address space need not be the same as the AST / Language
+ // default (e.g. in C / C++ auto vars are in the generic address space). At
+ // the AST level this is handled within CreateTempAlloca et al., but for the
+ // builtin / dynamic alloca we have to handle it here.
+ assert(!cir::MissingFeatures::addressSpace());
+
+ // Bitcast the alloca to the expected type.
+ return RValue::get(
+ builder.createBitcast(allocaAddr, builder.getVoidPtrTy()));
+ }
+
case Builtin::BIfabs:
case Builtin::BIfabsf:
case Builtin::BIfabsl:
diff --git a/clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp b/clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp
index 4e0a041d26ce1..72bbf08c79b16 100644
--- a/clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp
@@ -42,7 +42,8 @@ static void process(mlir::ModuleOp mod, cir::FuncOp func) {
if (alloca->getBlock() == &entryBlock)
return;
// Don't hoist allocas with dynamic alloca size.
- assert(!cir::MissingFeatures::opAllocaDynAllocSize());
+ if (alloca.getDynAllocSize())
+ return;
// Hoist allocas into the entry block.
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index ee9f58c829ca9..8e8cd2a63dcd5 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1053,9 +1053,12 @@ mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
cir::AllocaOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
- assert(!cir::MissingFeatures::opAllocaDynAllocSize());
- mlir::Value size = rewriter.create<mlir::LLVM::ConstantOp>(
- op.getLoc(), typeConverter->convertType(rewriter.getIndexType()), 1);
+ mlir::Value size =
+ op.isDynamic() ? adaptor.getDynAllocSize()
+ : rewriter.create<mlir::LLVM::ConstantOp>(
+ op.getLoc(),
+ typeConverter->convertType(rewriter.getIndexType()),
+ rewriter.getIntegerAttr(rewriter.getIndexType(), 1));
mlir::Type elementTy =
convertTypeForMemory(*getTypeConverter(), dataLayout, op.getAllocaType());
mlir::Type resultTy =
diff --git a/clang/test/CIR/CodeGen/builtin_call.cpp b/clang/test/CIR/CodeGen/builtin_call.cpp
index 09be7937a4330..d416841c5d6fe 100644
--- a/clang/test/CIR/CodeGen/builtin_call.cpp
+++ b/clang/test/CIR/CodeGen/builtin_call.cpp
@@ -258,3 +258,13 @@ void trap2() {
// LLVM: {{.+}}:
// LLVM-NEXT: call void @_Z2f1v()
// LLVM: }
+
+void *test_alloca(unsigned long n) {
+ return __builtin_alloca(n);
+}
+
+// CIR-LABEL: @_Z11test_allocam(
+// CIR: %{{.+}} = cir.alloca !u8i, !cir.ptr<!u8i>, %{{.+}} : !u64i, ["bi_alloca"]
+
+// LLVM-LABEL: @_Z11test_allocam(
+// LLVM: alloca i8, i64 %{{.+}}
diff --git a/clang/test/CIR/IR/alloca.cir b/clang/test/CIR/IR/alloca.cir
new file mode 100644
index 0000000000000..12f7e6ac6a914
--- /dev/null
+++ b/clang/test/CIR/IR/alloca.cir
@@ -0,0 +1,32 @@
+
+// RUN: cir-opt %s | FileCheck %s
+
+!u64i = !cir.int<u, 64>
+!u8i = !cir.int<u, 8>
+!void = !cir.void
+module {
+ cir.func dso_local @_Z11test_allocam(%arg0: !u64i) -> !cir.ptr<!void> {
+ %0 = cir.alloca !u64i, !cir.ptr<!u64i>, ["n", init] {alignment = 8 : i64}
+ %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__retval"] {alignment = 8 : i64}
+ cir.store %arg0, %0 : !u64i, !cir.ptr<!u64i>
+ %2 = cir.load align(8) %0 : !cir.ptr<!u64i>, !u64i
+ // Dynamically sized alloca
+ %3 = cir.alloca !u8i, !cir.ptr<!u8i>, %2 : !u64i, ["bi_alloca"] {alignment = 16 : i64}
+ %4 = cir.cast(bitcast, %3 : !cir.ptr<!u8i>), !cir.ptr<!void>
+ cir.store %4, %1 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+ %5 = cir.load %1 : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+ cir.return %5 : !cir.ptr<!void>
+ }
+
+ // CHECK: cir.func dso_local @_Z11test_allocam(%arg0: !u64i) -> !cir.ptr<!void> {
+ // CHECK: %0 = cir.alloca !u64i, !cir.ptr<!u64i>, ["n", init] {alignment = 8 : i64}
+ // CHECK: %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__retval"] {alignment = 8 : i64}
+ // CHECK: cir.store %arg0, %0 : !u64i, !cir.ptr<!u64i>
+ // CHECK: %2 = cir.load align(8) %0 : !cir.ptr<!u64i>, !u64i
+ // CHECK: %3 = cir.alloca !u8i, !cir.ptr<!u8i>, %2 : !u64i, ["bi_alloca"] {alignment = 16 : i64}
+ // CHECK: %4 = cir.cast(bitcast, %3 : !cir.ptr<!u8i>), !cir.ptr<!void>
+ // CHECK: cir.store %4, %1 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+ // CHECK: %5 = cir.load %1 : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+ // CHECK: cir.return %5 : !cir.ptr<!void>
+ // CHECK: }
+}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| const TargetInfo &TI = getContext().getTargetInfo(); | |
| const TargetInfo &ti = getContext().getTargetInfo(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a problem if there are multiple "bi_alloca" values in the same function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name string attribute isn't used for anything (or at least I couldn't find a use) so this shouldn't be an issue.
Also note that we have some precedence with array ctors and __array_idx: https://godbolt.org/z/dT3G4neYT
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add the OGCG checks? This test seems to have started drifting away from doing that for some reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a some missing OGCG checks with the exception of __builtin_expect and __builtin_expect_with_probability because OGCG doesn't lower to the LLVM intrinsic.
bcardosolopes
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM once existing comments are addressed
This patch adds support for the alloca builtin and extends AllocaOp with a dynamic size argument.
This patch adds support for the alloca builtin and extends AllocaOp with a dynamic size argument.