https://github.com/erichkeane updated https://github.com/llvm/llvm-project/pull/182960
>From c278c944f5275b7005a8031698a5207a906a04e0 Mon Sep 17 00:00:00 2001 From: erichkeane <[email protected]> Date: Mon, 23 Feb 2026 15:30:40 -0800 Subject: [PATCH 1/2] [CIR] Implement 'assume' attribute lowering This attribute applies to null statements and emits an assume-op sometimes. This patch adds this for statements, which includes the infrastructure for AttributedStmt lowering. --- clang/lib/CIR/CodeGen/CIRGenFunction.h | 2 + clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 33 ++++++++++ clang/test/CIR/CodeGen/assume-attr.cpp | 91 ++++++++++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 clang/test/CIR/CodeGen/assume-attr.cpp diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index cf1722e6cf6df..4a9a1710fdfae 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1391,6 +1391,8 @@ class CIRGenFunction : public CIRGenTypeCache { const Expr *memOrder, bool isStore, bool isLoad, bool isFence, llvm::function_ref<void(cir::MemOrder)> emitAtomicOp); + mlir::LogicalResult emitAttributedStmt(const AttributedStmt &s); + AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d, mlir::OpBuilder::InsertPoint ip = {}); diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index db3827340c455..3043686c1e156 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -85,6 +85,37 @@ mlir::LogicalResult CIRGenFunction::emitCompoundStmtWithoutScope( return result; } +mlir::LogicalResult +CIRGenFunction::emitAttributedStmt(const AttributedStmt &s) { + for (const auto *attr : s.getAttrs()) { + switch (attr->getKind()) { + default: + break; + case attr::NoMerge: + case attr::NoInline: + case attr::AlwaysInline: + case attr::NoConvergent: + case attr::MustTail: + case attr::Atomic: + case attr::HLSLControlFlowHint: + cgm.errorNYI(s.getSourceRange(), + "Unimplemented statement attribute: ", attr->getKind()); + break; + case attr::CXXAssume: { + const Expr *assumptionExpr = cast<CXXAssumeAttr>(attr)->getAssumption(); + if (getLangOpts().CXXAssumptions && builder.getInsertionBlock() && + !assumptionExpr->HasSideEffects(getContext())) { + mlir::Value assumptionValue = emitCheckedArgForAssume(assumptionExpr); + cir::AssumeOp::create(builder, getLoc(s.getSourceRange()), + assumptionValue); + } + } break; + } + } + + return emitStmt(s.getSubStmt(), /*useCurrentScope=*/true, s.getAttrs()); +} + mlir::LogicalResult CIRGenFunction::emitCompoundStmt(const CompoundStmt &s, Address *lastValue, AggValueSlot slot) { @@ -437,6 +468,8 @@ mlir::LogicalResult CIRGenFunction::emitSimpleStmt(const Stmt *s, return emitBreakStmt(cast<BreakStmt>(*s)); case Stmt::ReturnStmtClass: return emitReturnStmt(cast<ReturnStmt>(*s)); + case Stmt::AttributedStmtClass: + return emitAttributedStmt(cast<AttributedStmt>(*s)); } return mlir::success(); diff --git a/clang/test/CIR/CodeGen/assume-attr.cpp b/clang/test/CIR/CodeGen/assume-attr.cpp new file mode 100644 index 0000000000000..aa060540d602e --- /dev/null +++ b/clang/test/CIR/CodeGen/assume-attr.cpp @@ -0,0 +1,91 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefixes=LLVM,BOTH +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s --check-prefixes=OGCG,BOTH + + +bool hasSideEffect(); + +constexpr int globalVar = 5; + +void assume1(), assume2(), assume3(); + +void usage(int i, int j) { + // CIR: cir.func{{.*}}@_Z5usageii + // BOTH: define{{.*}}@_Z5usageii + + // CIR: %[[I:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] + // CIR: %[[J:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["j", init] + // CIR: %[[LOCAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["local", init, const] + // + // BOTH: %[[I:.*]] = alloca i32 + // BOTH: %[[J:.*]] = alloca i32 + // BOTH: %[[LOCAL:.*]] = alloca i32 + + [[assume(globalVar == i)]] + ; + + // CIR: %[[GET_GLOB_VAR:.*]] = cir.get_global @_ZL9globalVar + // CIR: %[[LOAD_GLOB_VAR:.*]] = cir.load {{.*}}%[[GET_GLOB_VAR]] + // CIR: %[[LOAD_I:.*]] = cir.load {{.*}}%[[I]] + // CIR: %[[CMP:.*]] = cir.cmp(eq, %[[LOAD_GLOB_VAR]], %[[LOAD_I]]) + // CIR: cir.assume %[[CMP]] : !cir.bool + // LLVM: %[[LOAD_GLOB_VAR:.*]] = load i32, ptr @_ZL9globalVar + // BOTH: %[[LOAD_I:.*]] = load i32, ptr %[[I]] + // LLVM: %[[CMP:.*]] = icmp eq i32 %[[LOAD_GLOB_VAR]], %[[LOAD_I]] + // OGCG: %[[CMP:.*]] = icmp eq i32 5, %[[LOAD_I]] + // BOTH: call void @llvm.assume(i1 %[[CMP]]) + assume1(); + // CIR: cir.call @_Z7assume1v() + // BOTH: call void @_Z7assume1v() + + constexpr int local = 12; + [[assume(j == i && j > local)]] + ; + // CIR: %[[LOAD_J:.*]] = cir.load {{.*}}%[[J]] + // CIR: %[[LOAD_I:.*]] = cir.load {{.*}}%[[I]] + // CIR: %[[J_EQ_I:.*]] = cir.cmp(eq, %[[LOAD_J]], %[[LOAD_I]]) + // CIR: %[[TERN:.*]] = cir.ternary(%[[J_EQ_I]], true { + // CIR-NEXT: %[[LOAD_J:.*]] = cir.load {{.*}}%[[J]] + // CIR-NEXT: %[[LOAD_LOCAL:.*]] = cir.load {{.*}}%[[LOCAL]] + // CIR-NEXT: %[[J_GT_LOCAL:.*]] = cir.cmp(gt, %[[LOAD_J]], %[[LOAD_LOCAL]]) + // CIR-NEXT: cir.yield %[[J_GT_LOCAL]] + // CIR-NEXT: }, false { + // CIR-NEXT: %[[FALSE:.*]] = cir.const #false + // CIR-NEXT: cir.yield %[[FALSE]] + // CIR-NEXT: }) : (!cir.bool) -> !cir.bool + // CIR: cir.assume %[[TERN:.*]] + // + // BOTH: %[[LOAD_J:.*]] = load i32, ptr %[[J]] + // BOTH: %[[LOAD_I:.*]] = load i32, ptr %[[I]] + // BOTH: %[[J_EQ_I:.*]] = icmp eq i32 %[[LOAD_J]], %[[LOAD_I]] + // BOTH: br i1 %[[J_EQ_I]], label %[[TRUE:.*]], label %[[FALSE:.*]] + // BOTH: [[TRUE]]: + // BOTH: %[[LOAD_J:.*]] = load i32, ptr %[[J]] + // LLVM: %[[LOAD_LOCAL:.*]] = load i32, ptr %[[LOCAL]] + // LLVM: %[[J_GT_LOCAL:.*]] = icmp sgt i32 %[[LOAD_J]], %[[LOAD_LOCAL]] + // OGCG: %[[J_GT_LOCAL:.*]] = icmp sgt i32 %[[LOAD_J]], 12 + // LLVM: br label %[[DONE:.*]] + // OGCG: br label %[[FALSE]] + // LLVM: [[FALSE]]: + // LLVM: br label %[[DONE]] + // LLVM: [[DONE]]: + // OGCG: [[FALSE]]: + // LLVM: %[[TERN:.*]] = phi i1 [ false, %[[FALSE]] ], [ %[[J_GT_LOCAL]], %[[TRUE]] ] + // OGCG: %[[TERN:.*]] = phi i1 [ false, %entry ], [ %[[J_GT_LOCAL]], %[[TRUE]] ] + // BOTH: call void @llvm.assume(i1 %[[TERN]]) + assume2(); + // CIR: cir.call @_Z7assume2v() + // BOTH: call void @_Z7assume2v() + + [[assume(hasSideEffect())]] + ; + // CIR-NOT: cir.assume + // BOTH-NOT: call void @llvm.assume + assume3(); + // CIR: cir.call @_Z7assume3v() + // BOTH: call void @_Z7assume3v() +} + >From 5279aaae3428dcd648fb71645c8a0aba3f6e22f2 Mon Sep 17 00:00:00 2001 From: Erich Keane <[email protected]> Date: Tue, 24 Feb 2026 06:24:24 -0800 Subject: [PATCH 2/2] remove auto that probably doesnt fit coding standard Co-authored-by: Sirui Mu <[email protected]> --- clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index 3043686c1e156..f4bd80f111f11 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -87,7 +87,7 @@ mlir::LogicalResult CIRGenFunction::emitCompoundStmtWithoutScope( mlir::LogicalResult CIRGenFunction::emitAttributedStmt(const AttributedStmt &s) { - for (const auto *attr : s.getAttrs()) { + for (const Attr *attr : s.getAttrs()) { switch (attr->getKind()) { default: break; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
