https://github.com/andykaylor updated https://github.com/llvm/llvm-project/pull/130869
>From a4e8aa13f97a6c73389822f6fdcf6f5970792462 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Tue, 11 Mar 2025 17:01:44 -0700 Subject: [PATCH 1/3] [CIR] Upstream support for emitting ignored statements This adds support for emitting ClangIR for statements whose value is ignored. The test case being added (CIR/CodeGen/basic.c) tests a few more things. The "f1" test case is the only part that's immediately relevant to this change, but the other cases were part of the same test in the incubator and they are supported so I brought in the entire test. --- clang/include/clang/CIR/MissingFeatures.h | 1 + clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 27 ++++ clang/lib/CIR/CodeGen/CIRGenFunction.h | 10 ++ clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 152 +++++++++++++++++++++- clang/test/CIR/CodeGen/basic.c | 53 ++++++++ 5 files changed, 239 insertions(+), 4 deletions(-) create mode 100644 clang/test/CIR/CodeGen/basic.c diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index ddfe654009644..e8d3eff79d0b2 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -83,6 +83,7 @@ struct MissingFeatures { static bool emitNullabilityCheck() { return false; } static bool astVarDeclInterface() { return false; } static bool stackSaveOp() { return false; } + static bool aggValueSlot() { return false; } }; } // namespace cir diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 07fb4cf8f1513..a33aa45f8a4fc 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -165,6 +165,33 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) { return LValue(); } +/// Emit code to compute the specified expression which +/// can have any type. The result is returned as an RValue struct. +RValue CIRGenFunction::emitAnyExpr(const Expr *e, bool ignoreResult) { + switch (CIRGenFunction::getEvaluationKind(e->getType())) { + case cir::TEK_Scalar: + return RValue::get(emitScalarExpr(e)); + case cir::TEK_Complex: + cgm.errorNYI(e->getSourceRange(), "emitAnyExpr: complex type"); + return RValue::get(nullptr); + case cir::TEK_Aggregate: + cgm.errorNYI(e->getSourceRange(), "emitAnyExpr: aggregate type"); + return RValue::get(nullptr); + } + llvm_unreachable("bad evaluation kind"); +} + +/// Emit code to compute the specified expression, ignoring the result. +void CIRGenFunction::emitIgnoredExpr(const Expr *e) { + if (e->isPRValue()) { + assert(!cir::MissingFeatures::aggValueSlot()); + return (void)emitAnyExpr(e, true); + } + + // Just emit it as an l-value and drop the result. + emitLValue(e); +} + mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty, mlir::Location loc, CharUnits alignment) { diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 72445f62232a4..ddb1c1c5dd229 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -154,6 +154,12 @@ class CIRGenFunction : public CIRGenTypeCache { const clang::LangOptions &getLangOpts() const { return cgm.getLangOpts(); } + /// Emit code to compute the specified expression which can have any type. The + /// result is returned as an RValue struct. If this is an aggregate + /// expression, the aggloc/agglocvolatile arguments indicate where the result + /// should be returned. + RValue emitAnyExpr(const clang::Expr *e, bool ignoreResult = false); + void finishFunction(SourceLocation endLoc); mlir::LogicalResult emitFunctionBody(const clang::Stmt *body); @@ -170,6 +176,10 @@ class CIRGenFunction : public CIRGenTypeCache { void emitCompoundStmtWithoutScope(const clang::CompoundStmt &s); + /// Emit code to compute the specified expression, + /// ignoring the result. + void emitIgnoredExpr(const clang::Expr *e); + mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s); mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s); diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index ed5d87a39704a..91627d5d5985a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -55,10 +55,154 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s, if (mlir::succeeded(emitSimpleStmt(s, useCurrentScope))) return mlir::success(); - // Only a subset of simple statements are supported at the moment. When more - // kinds of statements are supported, a - // switch (s->getStmtClass()) { - // will be added here. + switch (s->getStmtClass()) { + +#define STMT(Type, Base) +#define ABSTRACT_STMT(Op) +#define EXPR(Type, Base) case Stmt::Type##Class: +#include "clang/AST/StmtNodes.inc" + { + // Remember the block we came in on. + mlir::Block *incoming = builder.getInsertionBlock(); + assert(incoming && "expression emission must have an insertion point"); + + emitIgnoredExpr(cast<Expr>(s)); + + mlir::Block *outgoing = builder.getInsertionBlock(); + assert(outgoing && "expression emission cleared block!"); + return mlir::success(); + } + + case Stmt::OMPScopeDirectiveClass: + case Stmt::OMPErrorDirectiveClass: + case Stmt::NoStmtClass: + case Stmt::CXXCatchStmtClass: + case Stmt::SEHExceptStmtClass: + case Stmt::SEHFinallyStmtClass: + case Stmt::MSDependentExistsStmtClass: + case Stmt::NullStmtClass: + case Stmt::CompoundStmtClass: + case Stmt::DeclStmtClass: + case Stmt::LabelStmtClass: + case Stmt::AttributedStmtClass: + case Stmt::GotoStmtClass: + case Stmt::BreakStmtClass: + case Stmt::ContinueStmtClass: + case Stmt::DefaultStmtClass: + case Stmt::CaseStmtClass: + case Stmt::SEHLeaveStmtClass: + case Stmt::SYCLKernelCallStmtClass: + case Stmt::IfStmtClass: + case Stmt::SwitchStmtClass: + case Stmt::ForStmtClass: + case Stmt::WhileStmtClass: + case Stmt::DoStmtClass: + case Stmt::CoroutineBodyStmtClass: + case Stmt::CoreturnStmtClass: + case Stmt::CXXTryStmtClass: + case Stmt::CXXForRangeStmtClass: + case Stmt::IndirectGotoStmtClass: + case Stmt::ReturnStmtClass: + case Stmt::GCCAsmStmtClass: + case Stmt::MSAsmStmtClass: + case Stmt::OMPParallelDirectiveClass: + case Stmt::OMPTaskwaitDirectiveClass: + case Stmt::OMPTaskyieldDirectiveClass: + case Stmt::OMPBarrierDirectiveClass: + case Stmt::CapturedStmtClass: + case Stmt::ObjCAtTryStmtClass: + case Stmt::ObjCAtThrowStmtClass: + case Stmt::ObjCAtSynchronizedStmtClass: + case Stmt::ObjCForCollectionStmtClass: + case Stmt::ObjCAutoreleasePoolStmtClass: + case Stmt::SEHTryStmtClass: + case Stmt::OMPMetaDirectiveClass: + case Stmt::OMPCanonicalLoopClass: + case Stmt::OMPSimdDirectiveClass: + case Stmt::OMPTileDirectiveClass: + case Stmt::OMPUnrollDirectiveClass: + case Stmt::OMPForDirectiveClass: + case Stmt::OMPForSimdDirectiveClass: + case Stmt::OMPSectionsDirectiveClass: + case Stmt::OMPSectionDirectiveClass: + case Stmt::OMPSingleDirectiveClass: + case Stmt::OMPMasterDirectiveClass: + case Stmt::OMPCriticalDirectiveClass: + case Stmt::OMPParallelForDirectiveClass: + case Stmt::OMPParallelForSimdDirectiveClass: + case Stmt::OMPParallelMasterDirectiveClass: + case Stmt::OMPParallelSectionsDirectiveClass: + case Stmt::OMPTaskDirectiveClass: + case Stmt::OMPTaskgroupDirectiveClass: + case Stmt::OMPFlushDirectiveClass: + case Stmt::OMPDepobjDirectiveClass: + case Stmt::OMPScanDirectiveClass: + case Stmt::OMPOrderedDirectiveClass: + case Stmt::OMPAtomicDirectiveClass: + case Stmt::OMPTargetDirectiveClass: + case Stmt::OMPTeamsDirectiveClass: + case Stmt::OMPCancellationPointDirectiveClass: + case Stmt::OMPCancelDirectiveClass: + case Stmt::OMPTargetDataDirectiveClass: + case Stmt::OMPTargetEnterDataDirectiveClass: + case Stmt::OMPTargetExitDataDirectiveClass: + case Stmt::OMPTargetParallelDirectiveClass: + case Stmt::OMPTargetParallelForDirectiveClass: + case Stmt::OMPTaskLoopDirectiveClass: + case Stmt::OMPTaskLoopSimdDirectiveClass: + case Stmt::OMPMaskedTaskLoopDirectiveClass: + case Stmt::OMPMaskedTaskLoopSimdDirectiveClass: + case Stmt::OMPMasterTaskLoopDirectiveClass: + case Stmt::OMPMasterTaskLoopSimdDirectiveClass: + case Stmt::OMPParallelGenericLoopDirectiveClass: + case Stmt::OMPParallelMaskedDirectiveClass: + case Stmt::OMPParallelMaskedTaskLoopDirectiveClass: + case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass: + case Stmt::OMPParallelMasterTaskLoopDirectiveClass: + case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass: + case Stmt::OMPDistributeDirectiveClass: + case Stmt::OMPDistributeParallelForDirectiveClass: + case Stmt::OMPDistributeParallelForSimdDirectiveClass: + case Stmt::OMPDistributeSimdDirectiveClass: + case Stmt::OMPTargetParallelGenericLoopDirectiveClass: + case Stmt::OMPTargetParallelForSimdDirectiveClass: + case Stmt::OMPTargetSimdDirectiveClass: + case Stmt::OMPTargetTeamsGenericLoopDirectiveClass: + case Stmt::OMPTargetUpdateDirectiveClass: + case Stmt::OMPTeamsDistributeDirectiveClass: + case Stmt::OMPTeamsDistributeSimdDirectiveClass: + case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass: + case Stmt::OMPTeamsDistributeParallelForDirectiveClass: + case Stmt::OMPTeamsGenericLoopDirectiveClass: + case Stmt::OMPTargetTeamsDirectiveClass: + case Stmt::OMPTargetTeamsDistributeDirectiveClass: + case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass: + case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: + case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: + case Stmt::OMPInteropDirectiveClass: + case Stmt::OMPDispatchDirectiveClass: + case Stmt::OMPGenericLoopDirectiveClass: + case Stmt::OMPReverseDirectiveClass: + case Stmt::OMPInterchangeDirectiveClass: + case Stmt::OMPAssumeDirectiveClass: + case Stmt::OMPMaskedDirectiveClass: + case Stmt::OpenACCComputeConstructClass: + case Stmt::OpenACCLoopConstructClass: + case Stmt::OpenACCCombinedConstructClass: + case Stmt::OpenACCDataConstructClass: + case Stmt::OpenACCEnterDataConstructClass: + case Stmt::OpenACCExitDataConstructClass: + case Stmt::OpenACCHostDataConstructClass: + case Stmt::OpenACCWaitConstructClass: + case Stmt::OpenACCInitConstructClass: + case Stmt::OpenACCShutdownConstructClass: + case Stmt::OpenACCSetConstructClass: + case Stmt::OpenACCUpdateConstructClass: + case Stmt::ObjCAtCatchStmtClass: + case Stmt::ObjCAtFinallyStmtClass: + cgm.errorNYI(s->getSourceRange(), + std::string("emitStmt: ") + s->getStmtClassName()); + } return mlir::failure(); } diff --git a/clang/test/CIR/CodeGen/basic.c b/clang/test/CIR/CodeGen/basic.c new file mode 100644 index 0000000000000..8d067aefded66 --- /dev/null +++ b/clang/test/CIR/CodeGen/basic.c @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -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 -Wno-unused-value -fclangir -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM + +int f1(int i); + +int f1(int i) { + i; + return i; +} + +// CIR: module +// CIR-NEXT: cir.func @f1(%arg0: !cir.int<s, 32> loc({{.*}})) -> !cir.int<s, 32> +// CIR-NEXT: %[[I_PTR:.*]] = cir.alloca !cir.int<s, 32>, !cir.ptr<!cir.int<s, 32>>, ["i", init] {alignment = 4 : i64} +// CIR-NEXT: cir.store %arg0, %[[I_PTR]] : !cir.int<s, 32>, !cir.ptr<!cir.int<s, 32>> +// CIR-NEXT: %[[I_IGNORED:.*]] = cir.load %[[I_PTR]] : !cir.ptr<!cir.int<s, 32>>, !cir.int<s, 32> +// CIR-NEXT: %[[I:.*]] = cir.load %[[I_PTR]] : !cir.ptr<!cir.int<s, 32>>, !cir.int<s, 32> +// CIR-NEXT: cir.return %[[I]] : !cir.int<s, 32> + +// LLVM: define i32 @f1(i32 %[[I:.*]]) +// LLVM-NEXT: %[[I_PTR:.*]] = alloca i32, i64 1, align 4 +// LLVM-NEXT: store i32 %[[I]], ptr %[[I_PTR]], align 4 +// LLVM-NEXT: %[[I_IGNORED:.*]] = load i32, ptr %[[I_PTR]], align 4 +// LLVM-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 4 +// LLVM-NEXT: ret i32 %[[I]] + +int f2(void) { return 3; } + +// CIR: cir.func @f2() -> !cir.int<s, 32> +// CIR-NEXT: %[[THREE:.*]] = cir.const #cir.int<3> : !cir.int<s, 32> +// CIR-NEXT: cir.return %[[THREE]] : !cir.int<s, 32> + +// LLVM: define i32 @f2() +// LLVM-NEXT: ret i32 3 + +int f3(void) { + int i = 3; + return i; +} + +// CIR: cir.func @f3() -> !cir.int<s, 32> +// CIR-NEXT: %[[I_PTR:.*]] = cir.alloca !cir.int<s, 32>, !cir.ptr<!cir.int<s, 32>>, ["i", init] {alignment = 4 : i64} +// CIR-NEXT: %[[THREE:.*]] = cir.const #cir.int<3> : !cir.int<s, 32> +// CIR-NEXT: cir.store %[[THREE]], %[[I_PTR]] : !cir.int<s, 32>, !cir.ptr<!cir.int<s, 32>> +// CIR-NEXT: %[[I:.*]] = cir.load %[[I_PTR]] : !cir.ptr<!cir.int<s, 32>>, !cir.int<s, 32> +// CIR-NEXT: cir.return %[[I]] : !cir.int<s, 32> + +// LLVM: define i32 @f3() +// LLVM-NEXT: %[[I_PTR:.*]] = alloca i32, i64 1, align 4 +// LLVM-NEXT: store i32 3, ptr %[[I_PTR]], align 4 +// LLVM-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 4 +// LLVM-NEXT: ret i32 %[[I]] >From cf692675df6f83a0b799666e5bd637ee8d7e7188 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Wed, 12 Mar 2025 11:45:37 -0700 Subject: [PATCH 2/3] Add test checks for classic codegen, minor cleanup --- clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 3 ++- clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 7 ++++++- clang/test/CIR/CodeGen/basic.c | 25 +++++++++++++++++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index a33aa45f8a4fc..2d9ec41452a9d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -185,7 +185,8 @@ RValue CIRGenFunction::emitAnyExpr(const Expr *e, bool ignoreResult) { void CIRGenFunction::emitIgnoredExpr(const Expr *e) { if (e->isPRValue()) { assert(!cir::MissingFeatures::aggValueSlot()); - return (void)emitAnyExpr(e, true); + emitAnyExpr(e, true); + return; } // Just emit it as an l-value and drop the result. diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index 91627d5d5985a..d4476a5e9fa17 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -186,6 +186,7 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s, case Stmt::OMPInterchangeDirectiveClass: case Stmt::OMPAssumeDirectiveClass: case Stmt::OMPMaskedDirectiveClass: + case Stmt::OMPStripeDirectiveClass: case Stmt::OpenACCComputeConstructClass: case Stmt::OpenACCLoopConstructClass: case Stmt::OpenACCCombinedConstructClass: @@ -198,12 +199,16 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s, case Stmt::OpenACCShutdownConstructClass: case Stmt::OpenACCSetConstructClass: case Stmt::OpenACCUpdateConstructClass: + case Stmt::OpenACCCacheConstructClass: + case Stmt::OpenACCAtomicConstructClass: case Stmt::ObjCAtCatchStmtClass: case Stmt::ObjCAtFinallyStmtClass: cgm.errorNYI(s->getSourceRange(), std::string("emitStmt: ") + s->getStmtClassName()); + return mlir::failure(); } - return mlir::failure(); + + llvm_unreachable("Unexpected statement class"); } mlir::LogicalResult CIRGenFunction::emitSimpleStmt(const Stmt *s, diff --git a/clang/test/CIR/CodeGen/basic.c b/clang/test/CIR/CodeGen/basic.c index 8d067aefded66..754f11f1361ba 100644 --- a/clang/test/CIR/CodeGen/basic.c +++ b/clang/test/CIR/CodeGen/basic.c @@ -1,7 +1,9 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -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 -Wno-unused-value -fclangir -emit-llvm %s -o %t.ll -// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG int f1(int i); @@ -25,6 +27,14 @@ int f1(int i) { // LLVM-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 4 // LLVM-NEXT: ret i32 %[[I]] +// OGCG: define{{.*}} i32 @f1(i32 noundef %[[I:.*]]) +// OGCG-NEXT: entry: +// OGCG-NEXT: %[[I_PTR:.*]] = alloca i32, align 4 +// OGCG-NEXT: store i32 %[[I]], ptr %[[I_PTR]], align 4 +// OGCG-NEXT: %[[I_IGNORED:.*]] = load i32, ptr %[[I_PTR]], align 4 +// OGCG-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 4 +// OGCG-NEXT: ret i32 %[[I]] + int f2(void) { return 3; } // CIR: cir.func @f2() -> !cir.int<s, 32> @@ -34,6 +44,10 @@ int f2(void) { return 3; } // LLVM: define i32 @f2() // LLVM-NEXT: ret i32 3 +// OGCG: define{{.*}} i32 @f2() +// OGCG-NEXT: entry: +// OGCG-NEXT: ret i32 3 + int f3(void) { int i = 3; return i; @@ -51,3 +65,10 @@ int f3(void) { // LLVM-NEXT: store i32 3, ptr %[[I_PTR]], align 4 // LLVM-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 4 // LLVM-NEXT: ret i32 %[[I]] + +// OGCG: define{{.*}} i32 @f3 +// OGCG-NEXT: entry: +// OGCG-NEXT: %[[I_PTR:.*]] = alloca i32, align 4 +// OGCG-NEXT: store i32 3, ptr %[[I_PTR]], align 4 +// OGCG-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 4 +// OGCG-NEXT: ret i32 %[[I]] >From 2b37483e380b1c7ac2c9b39814f39a2957706e94 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Wed, 12 Mar 2025 11:59:45 -0700 Subject: [PATCH 3/3] Stop using intermediate files for lit test --- clang/test/CIR/CodeGen/basic.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/clang/test/CIR/CodeGen/basic.c b/clang/test/CIR/CodeGen/basic.c index 754f11f1361ba..7ae3bcbd79cb8 100644 --- a/clang/test/CIR/CodeGen/basic.c +++ b/clang/test/CIR/CodeGen/basic.c @@ -1,9 +1,6 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -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 -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll -// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll -// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o - | FileCheck %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o - | FileCheck %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o - | FileCheck %s -check-prefix=OGCG int f1(int i); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits