Skip to content

Commit

Permalink
[CIR] Make use of !invariant.group metadata for const allocas
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Lancern committed Nov 26, 2024
1 parent 41078e9 commit 2ae7176
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 22 deletions.
8 changes: 7 additions & 1 deletion clang/lib/CIR/Dialect/Transforms/HoistAllocas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
17 changes: 12 additions & 5 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down Expand Up @@ -1480,11 +1479,15 @@ mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite(
alignment = *alignOpt;
}

// TODO: nontemporal, invariant, syncscope.
auto addrAllocaOp =
mlir::dyn_cast_if_present<cir::AllocaOp>(op.getAddr().getDefiningOp());
auto invariant = addrAllocaOp && addrAllocaOp.getConstant();

// TODO: nontemporal, syncscope.
rewriter.replaceOpWithNewOp<mlir::LLVM::LoadOp>(
op, llvmTy, adaptor.getAddr(), /* alignment */ alignment,
op.getIsVolatile(), /* nontemporal */ false,
/* invariant */ false, /* invariantGroup */ false, ordering);
/* invariant */ false, /* invariantGroup */ invariant, ordering);
return mlir::LogicalResult::success();
}

Expand All @@ -1505,10 +1508,14 @@ mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite(
alignment = *alignOpt;
}

auto addrAllocaOp =
mlir::dyn_cast_if_present<cir::AllocaOp>(op.getAddr().getDefiningOp());
auto invariant = addrAllocaOp && addrAllocaOp.getConstant();

// TODO: nontemporal, syncscope.
rewriter.replaceOpWithNewOp<mlir::LLVM::StoreOp>(
op, adaptor.getValue(), adaptor.getAddr(), alignment, op.getIsVolatile(),
/* nontemporal */ false, /* invariantGroup */ false, ordering);
/* nontemporal */ false, /* invariantGroup */ invariant, ordering);
return mlir::LogicalResult::success();
}

Expand Down
50 changes: 34 additions & 16 deletions clang/test/CIR/CodeGen/const-alloca.cpp
Original file line number Diff line number Diff line change
@@ -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 &);
Expand All @@ -8,33 +10,33 @@ void local_const_int() {
const int x = produce_int();
}

// CHECK-LABEL: @_Z15local_const_intv
// CHECK: %{{.+}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init, const]
// CHECK: }
// CIR-LABEL: @_Z15local_const_intv
// CIR: %{{.+}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init, const]
// CIR: }

void param_const_int(const int x) {}

// CHECK-LABEL: @_Z15param_const_inti
// CHECK: %{{.+}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init, const]
// CHECK: }
// CIR-LABEL: @_Z15param_const_inti
// CIR: %{{.+}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["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<!s32i>, ["x", init, const]
// CHECK: }
// CIR-LABEL: @_Z19local_constexpr_intv
// CIR: %{{.+}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init, const]
// CIR: }

void local_reference() {
int x = 0;
int &r = x;
}

// CHECK-LABEL: @_Z15local_referencev
// CHECK: %{{.+}} = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["r", init, const]
// CHECK: }
// CIR-LABEL: @_Z15local_referencev
// CIR: %{{.+}} = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["r", init, const]
// CIR: }

struct Foo {
int a;
Expand All @@ -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<!ty_Foo>, ["x", init, const]
// CHECK: }
// CIR-LABEL: @_Z18local_const_structv
// CIR: %{{.+}} = cir.alloca !ty_Foo, !cir.ptr<!ty_Foo>, ["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<!s32i>, ["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: }

0 comments on commit 2ae7176

Please sign in to comment.