From 2ae71767522e3295523410d9578c58169c4f0b7c Mon Sep 17 00:00:00 2001 From: Sirui Mu Date: Mon, 25 Nov 2024 00:51:13 +0800 Subject: [PATCH] [CIR] Make use of !invariant.group metadata for const allocas This patch updates the LLVM lowering part of load and stores to const allocas and makes use of the !invariant.group metadata in the result LLVM IR. The HoistAlloca pass is also updated. The const flag on a hoisted alloca is removed for now since their uses are not always invariants. Will update in later patches to teach their invariants. --- .../CIR/Dialect/Transforms/HoistAllocas.cpp | 8 ++- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 17 +++++-- clang/test/CIR/CodeGen/const-alloca.cpp | 50 +++++++++++++------ 3 files changed, 53 insertions(+), 22 deletions(-) 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: }