[clang] [CIR] Add CIRGenUtils.h for shared CIR codegen utilities (PR #172735)
Andrzej WarzyĆski via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 16 08:06:49 PST 2026
https://github.com/banach-space updated https://github.com/llvm/llvm-project/pull/172735
>From df25867d154bd7fe53378142ab4585aaccabd6d1 Mon Sep 17 00:00:00 2001
From: Andrzej Warzynski <andrzej.warzynski at arm.com>
Date: Wed, 17 Dec 2025 20:41:31 +0000
Subject: [PATCH] [CIR] Add CIRGenUtils.h for shared CIR codegen utilities
Extract `emitIntrinsicCallOp`, which was previously defined
independently in CIRGenBuiltinAArch64.cpp and CIRGenBuiltinX86.cpp, into
a shared header (CIRGenUtils.h).
---
clang/lib/CIR/CodeGen/CIRGenBuilder.h | 9 ++
.../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 17 +--
clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 129 ++++++++----------
3 files changed, 71 insertions(+), 84 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index ff492edf0b04e..638638ff768fe 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -668,6 +668,15 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
getConstant(loc, cir::PoisonAttr::get(vec1.getType()));
return createVecShuffle(loc, vec1, poison, mask);
}
+
+ template <typename... Operands>
+ mlir::Value emitIntrinsicCallOp(mlir::Location loc, const llvm::StringRef str,
+ const mlir::Type &resTy, Operands &&...op) {
+ return cir::LLVMIntrinsicCallOp::create(*this, loc,
+ this->getStringAttr(str), resTy,
+ std::forward<Operands>(op)...)
+ .getResult();
+ }
};
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 93089eb585aa7..7791baac95f54 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -31,23 +31,12 @@ using namespace clang;
using namespace clang::CIRGen;
using namespace llvm;
-template <typename... Operands>
-static mlir::Value emitIntrinsicCallOp(CIRGenBuilderTy &builder,
- mlir::Location loc, const StringRef str,
- const mlir::Type &resTy,
- Operands &&...op) {
- return cir::LLVMIntrinsicCallOp::create(builder, loc,
- builder.getStringAttr(str), resTy,
- std::forward<Operands>(op)...)
- .getResult();
-}
-
// Generate vscale * scalingFactor
static mlir::Value genVscaleTimesFactor(mlir::Location loc,
CIRGenBuilderTy builder,
mlir::Type cirTy,
int32_t scalingFactor) {
- mlir::Value vscale = emitIntrinsicCallOp(builder, loc, "vscale", cirTy);
+ mlir::Value vscale = builder.emitIntrinsicCallOp(loc, "vscale", cirTy);
return builder.createNUWAMul(loc, vscale,
builder.getUInt64(scalingFactor, loc));
}
@@ -240,8 +229,8 @@ CIRGenFunction::emitAArch64SVEBuiltinExpr(unsigned builtinID,
auto retTy = convertType(expr->getType());
- auto call = emitIntrinsicCallOp(builder, loc, llvmIntrName, retTy,
- mlir::ValueRange{ops});
+ auto call = builder.emitIntrinsicCallOp(loc, llvmIntrName, retTy,
+ mlir::ValueRange{ops});
if (call.getType() == retTy)
return call;
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index 497462a465145..5638648d296d8 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -31,17 +31,6 @@
using namespace clang;
using namespace clang::CIRGen;
-template <typename... Operands>
-static mlir::Value emitIntrinsicCallOp(CIRGenBuilderTy &builder,
- mlir::Location loc, const StringRef str,
- const mlir::Type &resTy,
- Operands &&...op) {
- return cir::LLVMIntrinsicCallOp::create(builder, loc,
- builder.getStringAttr(str), resTy,
- std::forward<Operands>(op)...)
- .getResult();
-}
-
// OG has unordered comparison as a form of optimization in addition to
// ordered comparison, while CIR doesn't.
//
@@ -166,8 +155,8 @@ static mlir::Value emitX86CompressExpand(CIRGenBuilderTy &builder,
auto resultTy = cast<cir::VectorType>(mask.getType());
mlir::Value maskValue = getMaskVecValue(
builder, loc, inputVector, cast<cir::VectorType>(resultTy).getSize());
- return emitIntrinsicCallOp(builder, loc, id, resultTy,
- mlir::ValueRange{source, mask, maskValue});
+ return builder.emitIntrinsicCallOp(loc, id, resultTy,
+ mlir::ValueRange{source, mask, maskValue});
}
static mlir::Value emitX86Select(CIRGenBuilderTy &builder, mlir::Location loc,
@@ -194,8 +183,8 @@ static mlir::Value emitX86MaskAddLogic(CIRGenBuilderTy &builder,
mlir::Value lhsVec = getMaskVecValue(builder, loc, ops[0], numElts);
mlir::Value rhsVec = getMaskVecValue(builder, loc, ops[1], numElts);
mlir::Type vecTy = lhsVec.getType();
- mlir::Value resVec = emitIntrinsicCallOp(builder, loc, intrinsicName, vecTy,
- mlir::ValueRange{lhsVec, rhsVec});
+ mlir::Value resVec = builder.emitIntrinsicCallOp(
+ loc, intrinsicName, vecTy, mlir::ValueRange{lhsVec, rhsVec});
return builder.createBitcast(resVec, ops[0].getType());
}
@@ -260,8 +249,8 @@ static mlir::Value emitX86MaskTest(CIRGenBuilderTy &builder, mlir::Location loc,
mlir::Value lhsVec = getMaskVecValue(builder, loc, ops[0], numElts);
mlir::Value rhsVec = getMaskVecValue(builder, loc, ops[1], numElts);
mlir::Type resTy = builder.getSInt32Ty();
- return emitIntrinsicCallOp(builder, loc, intrinsicName, resTy,
- mlir::ValueRange{lhsVec, rhsVec});
+ return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy,
+ mlir::ValueRange{lhsVec, rhsVec});
}
static mlir::Value emitX86MaskedCompareResult(CIRGenBuilderTy &builder,
@@ -408,8 +397,8 @@ static mlir::Value emitX86FunnelShift(CIRGenBuilderTy &builder,
}
const StringRef intrinsicName = isRight ? "fshr" : "fshl";
- return emitIntrinsicCallOp(builder, location, intrinsicName, op0Ty,
- mlir::ValueRange{op0, op1, amt});
+ return builder.emitIntrinsicCallOp(location, intrinsicName, op0Ty,
+ mlir::ValueRange{op0, op1, amt});
}
static mlir::Value emitX86Muldq(CIRGenBuilderTy &builder, mlir::Location loc,
@@ -459,8 +448,8 @@ static mlir::Value emitX86CvtF16ToFloatExpr(CIRGenBuilderTy &builder,
auto constOp = ops[3].getDefiningOp<cir::ConstantOp>();
assert(constOp && "Expected constant operand");
if (constOp.getIntValue().getZExtValue() != 4) {
- return emitIntrinsicCallOp(builder, loc, "x86.avx512.mask.vcvtph2ps.512",
- dstTy, ops);
+ return builder.emitIntrinsicCallOp(loc, "x86.avx512.mask.vcvtph2ps.512",
+ dstTy, ops);
}
}
@@ -593,7 +582,7 @@ static mlir::Value emitX86Fpclass(CIRGenBuilderTy &builder, mlir::Location loc,
auto cmpResultTy = cir::VectorType::get(builder.getSIntNTy(1), numElts);
mlir::Value fpclass =
- emitIntrinsicCallOp(builder, loc, intrinsicName, cmpResultTy, ops);
+ builder.emitIntrinsicCallOp(loc, intrinsicName, cmpResultTy, ops);
return emitX86MaskedCompareResult(builder, fpclass, numElts, maskIn, loc);
}
@@ -604,8 +593,8 @@ static mlir::Value emitX86Aes(CIRGenBuilderTy &builder, mlir::Location loc,
mlir::Type vecType =
mlir::cast<cir::PointerType>(ops[0].getType()).getPointee();
cir::RecordType rstRecTy = builder.getAnonRecordTy({retType, vecType});
- mlir::Value rstValueRec = emitIntrinsicCallOp(
- builder, loc, intrinsicName, rstRecTy, mlir::ValueRange{ops[1], ops[2]});
+ mlir::Value rstValueRec = builder.emitIntrinsicCallOp(
+ loc, intrinsicName, rstRecTy, mlir::ValueRange{ops[1], ops[2]});
// Extract the first return value and truncate it to 1 bit, then cast result
// to bool value.
@@ -662,7 +651,7 @@ static mlir::Value emitX86Aeswide(CIRGenBuilderTy &builder, mlir::Location loc,
}
cir::RecordType rstRecTy = builder.getAnonRecordTy(recTypes);
mlir::Value rstValueRec =
- emitIntrinsicCallOp(builder, loc, intrinsicName, rstRecTy, arguments);
+ builder.emitIntrinsicCallOp(loc, intrinsicName, rstRecTy, arguments);
// Extract the first return value and truncate it to 1 bit, then cast result
// to bool value.
@@ -752,20 +741,20 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
default:
return std::nullopt;
case X86::BI_mm_clflush:
- return emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()),
- "x86.sse2.clflush", voidTy, ops[0]);
+ return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
+ "x86.sse2.clflush", voidTy, ops[0]);
case X86::BI_mm_lfence:
- return emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()),
- "x86.sse2.lfence", voidTy);
+ return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
+ "x86.sse2.lfence", voidTy);
case X86::BI_mm_pause:
- return emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()),
- "x86.sse2.pause", voidTy);
+ return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
+ "x86.sse2.pause", voidTy);
case X86::BI_mm_mfence:
- return emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()),
- "x86.sse2.mfence", voidTy);
+ return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
+ "x86.sse2.mfence", voidTy);
case X86::BI_mm_sfence:
- return emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()),
- "x86.sse.sfence", voidTy);
+ return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
+ "x86.sse.sfence", voidTy);
case X86::BI_mm_prefetch:
case X86::BI__rdtsc:
case X86::BI__builtin_ia32_rdtscp: {
@@ -779,16 +768,16 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
case X86::BI__builtin_ia32_lzcnt_u64: {
mlir::Location loc = getLoc(expr->getExprLoc());
mlir::Value isZeroPoison = builder.getFalse(loc);
- return emitIntrinsicCallOp(builder, loc, "ctlz", ops[0].getType(),
- mlir::ValueRange{ops[0], isZeroPoison});
+ return builder.emitIntrinsicCallOp(loc, "ctlz", ops[0].getType(),
+ mlir::ValueRange{ops[0], isZeroPoison});
}
case X86::BI__builtin_ia32_tzcnt_u16:
case X86::BI__builtin_ia32_tzcnt_u32:
case X86::BI__builtin_ia32_tzcnt_u64: {
mlir::Location loc = getLoc(expr->getExprLoc());
mlir::Value isZeroPoison = builder.getFalse(loc);
- return emitIntrinsicCallOp(builder, loc, "cttz", ops[0].getType(),
- mlir::ValueRange{ops[0], isZeroPoison});
+ return builder.emitIntrinsicCallOp(loc, "cttz", ops[0].getType(),
+ mlir::ValueRange{ops[0], isZeroPoison});
}
case X86::BI__builtin_ia32_undef128:
case X86::BI__builtin_ia32_undef256:
@@ -849,15 +838,15 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
mlir::Location loc = getLoc(expr->getExprLoc());
Address tmp = createMemTemp(expr->getArg(0)->getType(), loc);
builder.createStore(loc, ops[0], tmp);
- return emitIntrinsicCallOp(builder, loc, "x86.sse.ldmxcsr",
- builder.getVoidTy(), tmp.getPointer());
+ return builder.emitIntrinsicCallOp(loc, "x86.sse.ldmxcsr",
+ builder.getVoidTy(), tmp.getPointer());
}
case X86::BI_mm_getcsr:
case X86::BI__builtin_ia32_stmxcsr: {
mlir::Location loc = getLoc(expr->getExprLoc());
Address tmp = createMemTemp(expr->getType(), loc);
- emitIntrinsicCallOp(builder, loc, "x86.sse.stmxcsr", builder.getVoidTy(),
- tmp.getPointer());
+ builder.emitIntrinsicCallOp(loc, "x86.sse.stmxcsr", builder.getVoidTy(),
+ tmp.getPointer());
return builder.createLoad(loc, tmp);
}
case X86::BI__builtin_ia32_xsave:
@@ -936,15 +925,15 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
// Mlo = (uint32_t)ops[1] - extract low 32 bits by truncation
mlir::Value mlo = builder.createIntCast(ops[1], i32Ty);
- return emitIntrinsicCallOp(builder, loc, intrinsicName, voidTy,
- mlir::ValueRange{ops[0], mhi, mlo});
+ return builder.emitIntrinsicCallOp(loc, intrinsicName, voidTy,
+ mlir::ValueRange{ops[0], mhi, mlo});
}
case X86::BI__builtin_ia32_xgetbv:
case X86::BI_xgetbv:
// xgetbv reads the extended control register specified by ops[0] (ECX)
// and returns the 64-bit value
- return emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()),
- "x86.xgetbv", builder.getUInt64Ty(), ops[0]);
+ return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()), "x86.xgetbv",
+ builder.getUInt64Ty(), ops[0]);
case X86::BI__builtin_ia32_storedqudi128_mask:
case X86::BI__builtin_ia32_storedqusi128_mask:
case X86::BI__builtin_ia32_storedquhi128_mask:
@@ -1285,8 +1274,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
std::min(cast<cir::VectorType>(ops[0].getType()).getSize(),
cast<cir::VectorType>(ops[2].getType()).getSize());
ops[3] = getMaskVecValue(builder, loc, ops[3], minElts);
- return emitIntrinsicCallOp(builder, loc, intrinsicName,
- convertType(expr->getType()), ops);
+ return builder.emitIntrinsicCallOp(loc, intrinsicName,
+ convertType(expr->getType()), ops);
}
case X86::BI__builtin_ia32_scattersiv8df:
case X86::BI__builtin_ia32_scattersiv16sf:
@@ -1396,8 +1385,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
cast<cir::VectorType>(ops[3].getType()).getSize());
ops[1] = getMaskVecValue(builder, loc, ops[1], minElts);
- return emitIntrinsicCallOp(builder, loc, intrinsicName,
- convertType(expr->getType()), ops);
+ return builder.emitIntrinsicCallOp(loc, intrinsicName,
+ convertType(expr->getType()), ops);
}
case X86::BI__builtin_ia32_vextractf128_pd256:
case X86::BI__builtin_ia32_vextractf128_ps256:
@@ -1970,9 +1959,9 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
case X86::BI__builtin_ia32_reduce_fadd_ph256:
case X86::BI__builtin_ia32_reduce_fadd_ph128: {
assert(!cir::MissingFeatures::fastMathFlags());
- return emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()),
- "vector.reduce.fadd", ops[0].getType(),
- mlir::ValueRange{ops[0], ops[1]});
+ return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
+ "vector.reduce.fadd", ops[0].getType(),
+ mlir::ValueRange{ops[0], ops[1]});
}
case X86::BI__builtin_ia32_reduce_fmul_pd512:
case X86::BI__builtin_ia32_reduce_fmul_ps512:
@@ -1980,9 +1969,9 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
case X86::BI__builtin_ia32_reduce_fmul_ph256:
case X86::BI__builtin_ia32_reduce_fmul_ph128: {
assert(!cir::MissingFeatures::fastMathFlags());
- return emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()),
- "vector.reduce.fmul", ops[0].getType(),
- mlir::ValueRange{ops[0], ops[1]});
+ return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
+ "vector.reduce.fmul", ops[0].getType(),
+ mlir::ValueRange{ops[0], ops[1]});
}
case X86::BI__builtin_ia32_reduce_fmax_pd512:
case X86::BI__builtin_ia32_reduce_fmax_ps512:
@@ -1991,9 +1980,9 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
case X86::BI__builtin_ia32_reduce_fmax_ph128: {
assert(!cir::MissingFeatures::fastMathFlags());
cir::VectorType vecTy = cast<cir::VectorType>(ops[0].getType());
- return emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()),
- "vector.reduce.fmax", vecTy.getElementType(),
- mlir::ValueRange{ops[0]});
+ return builder.emitIntrinsicCallOp(
+ getLoc(expr->getExprLoc()), "vector.reduce.fmax",
+ vecTy.getElementType(), mlir::ValueRange{ops[0]});
}
case X86::BI__builtin_ia32_reduce_fmin_pd512:
case X86::BI__builtin_ia32_reduce_fmin_ps512:
@@ -2002,9 +1991,9 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
case X86::BI__builtin_ia32_reduce_fmin_ph128: {
assert(!cir::MissingFeatures::fastMathFlags());
cir::VectorType vecTy = cast<cir::VectorType>(ops[0].getType());
- return emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()),
- "vector.reduce.fmin", vecTy.getElementType(),
- mlir::ValueRange{ops[0]});
+ return builder.emitIntrinsicCallOp(
+ getLoc(expr->getExprLoc()), "vector.reduce.fmin",
+ vecTy.getElementType(), mlir::ValueRange{ops[0]});
}
case X86::BI__builtin_ia32_rdrand16_step:
case X86::BI__builtin_ia32_rdrand32_step:
@@ -2072,9 +2061,9 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
cir::RecordType::get(&getMLIRContext(), {resVector, resVector}, false,
false, cir::RecordType::RecordKind::Struct);
- mlir::Value call =
- emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()), intrinsicName,
- resRecord, mlir::ValueRange{ops[0], ops[1]});
+ mlir::Value call = builder.emitIntrinsicCallOp(
+ getLoc(expr->getExprLoc()), intrinsicName, resRecord,
+ mlir::ValueRange{ops[0], ops[1]});
mlir::Value result =
cir::ExtractMemberOp::create(builder, loc, resVector, call, 0);
result = emitX86MaskedCompareResult(builder, result, numElts, nullptr, loc);
@@ -2176,8 +2165,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
args.push_back(ops[1]);
args.push_back(mask);
- return emitIntrinsicCallOp(
- builder, loc, "x86.avx512bf16.mask.cvtneps2bf16.128", resTy, args);
+ return builder.emitIntrinsicCallOp(
+ loc, "x86.avx512bf16.mask.cvtneps2bf16.128", resTy, args);
}
case X86::BI__builtin_ia32_cvtneps2bf16_256_mask:
case X86::BI__builtin_ia32_cvtneps2bf16_512_mask: {
@@ -2191,8 +2180,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
intrinsicName = "x86.avx512bf16.cvtneps2bf16.512";
}
- mlir::Value res = emitIntrinsicCallOp(builder, loc, intrinsicName, resTy,
- mlir::ValueRange{ops[0]});
+ mlir::Value res = builder.emitIntrinsicCallOp(loc, intrinsicName, resTy,
+ mlir::ValueRange{ops[0]});
return emitX86Select(builder, loc, ops[2], res, ops[1]);
}
More information about the cfe-commits
mailing list