diff --git a/clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp b/clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp index 003e5425ebaa..31e449a42d76 100644 --- a/clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp +++ b/clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp @@ -48,8 +48,14 @@ static void process(cir::FuncOp func) { mlir::Operation *insertPoint = &*entryBlock.begin(); - for (auto alloca : allocas) + for (auto alloca : allocas) { alloca->moveBefore(insertPoint); + if (alloca.getConstant()) { + // For now, we remove the const flag on nested allocas for constant + // variables when hoisting them. + alloca.setConstant(false); + } + } } void HoistAllocasPass::runOnOperation() { diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index ad97f2a9b56d..a3f207143b95 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -949,8 +949,7 @@ mlir::LogicalResult CIRToLLVMVTTAddrPointOpLowering::matchAndRewrite( if (op.getSymAddr()) { if (op.getOffset() == 0) { - rewriter.replaceAllUsesWith(op, llvmAddr); - rewriter.eraseOp(op); + rewriter.replaceOp(op, {llvmAddr}); return mlir::success(); } @@ -1480,11 +1479,15 @@ mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite( alignment = *alignOpt; } - // TODO: nontemporal, invariant, syncscope. + auto addrAllocaOp = + mlir::dyn_cast_if_present(op.getAddr().getDefiningOp()); + auto invariant = addrAllocaOp && addrAllocaOp.getConstant(); + + // TODO: nontemporal, syncscope. rewriter.replaceOpWithNewOp( op, llvmTy, adaptor.getAddr(), /* alignment */ alignment, op.getIsVolatile(), /* nontemporal */ false, - /* invariant */ false, /* invariantGroup */ false, ordering); + /* invariant */ false, /* invariantGroup */ invariant, ordering); return mlir::LogicalResult::success(); } @@ -1505,10 +1508,14 @@ mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite( alignment = *alignOpt; } + auto addrAllocaOp = + mlir::dyn_cast_if_present(op.getAddr().getDefiningOp()); + auto invariant = addrAllocaOp && addrAllocaOp.getConstant(); + // TODO: nontemporal, syncscope. rewriter.replaceOpWithNewOp( op, adaptor.getValue(), adaptor.getAddr(), alignment, op.getIsVolatile(), - /* nontemporal */ false, /* invariantGroup */ false, ordering); + /* nontemporal */ false, /* invariantGroup */ invariant, ordering); return mlir::LogicalResult::success(); } diff --git a/clang/test/CIR/CodeGen/const-alloca.cpp b/clang/test/CIR/CodeGen/const-alloca.cpp index c15e77d306ed..9146006694af 100644 --- a/clang/test/CIR/CodeGen/const-alloca.cpp +++ b/clang/test/CIR/CodeGen/const-alloca.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -// RUN: FileCheck --input-file=%t.cir %s +// RUN: FileCheck --input-file=%t.cir --check-prefix=CIR %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll --check-prefix=LLVM %s int produce_int(); void blackbox(const int &); @@ -8,33 +10,33 @@ void local_const_int() { const int x = produce_int(); } -// CHECK-LABEL: @_Z15local_const_intv -// CHECK: %{{.+}} = cir.alloca !s32i, !cir.ptr, ["x", init, const] -// CHECK: } +// CIR-LABEL: @_Z15local_const_intv +// CIR: %{{.+}} = cir.alloca !s32i, !cir.ptr, ["x", init, const] +// CIR: } void param_const_int(const int x) {} -// CHECK-LABEL: @_Z15param_const_inti -// CHECK: %{{.+}} = cir.alloca !s32i, !cir.ptr, ["x", init, const] -// CHECK: } +// CIR-LABEL: @_Z15param_const_inti +// CIR: %{{.+}} = cir.alloca !s32i, !cir.ptr, ["x", init, const] +// CIR: } void local_constexpr_int() { constexpr int x = 42; blackbox(x); } -// CHECK-LABEL: @_Z19local_constexpr_intv -// CHECK: %{{.+}} = cir.alloca !s32i, !cir.ptr, ["x", init, const] -// CHECK: } +// CIR-LABEL: @_Z19local_constexpr_intv +// CIR: %{{.+}} = cir.alloca !s32i, !cir.ptr, ["x", init, const] +// CIR: } void local_reference() { int x = 0; int &r = x; } -// CHECK-LABEL: @_Z15local_referencev -// CHECK: %{{.+}} = cir.alloca !cir.ptr, !cir.ptr>, ["r", init, const] -// CHECK: } +// CIR-LABEL: @_Z15local_referencev +// CIR: %{{.+}} = cir.alloca !cir.ptr, !cir.ptr>, ["r", init, const] +// CIR: } struct Foo { int a; @@ -47,6 +49,22 @@ void local_const_struct() { const Foo x = produce_foo(); } -// CHECK-LABEL: @_Z18local_const_structv -// CHECK: %{{.+}} = cir.alloca !ty_Foo, !cir.ptr, ["x", init, const] -// CHECK: } +// CIR-LABEL: @_Z18local_const_structv +// CIR: %{{.+}} = cir.alloca !ty_Foo, !cir.ptr, ["x", init, const] +// CIR: } + +int local_const_load_store() { + const int x = produce_int(); + int y = x; + return y; +} + +// CIR-LABEL: @_Z22local_const_load_storev +// CIR: %{{.+}} = cir.alloca !s32i, !cir.ptr, ["x", init, const] {alignment = 4 : i64} +// CIR: } + +// LLVM-LABEL: @_Z22local_const_load_storev +// LLVM: %[[#INIT:]] = call i32 @_Z11produce_intv() +// LLVM-NEXT: store i32 %[[#INIT]], ptr %[[#SLOT:]], align 4, !dbg !{{.+}}, !invariant.group !{{.+}} +// LLVM-NEXT: %{{.+}} = load i32, ptr %[[#SLOT]], align 4, !dbg !{{.+}}, !invariant.group !{{.+}} +// LLVM: }