Skip to content

Commit 5586dbb

Browse files
Upstream CIR codegen for vec_ext x86 builtins
1 parent 938f521 commit 5586dbb

File tree

5 files changed

+86
-2
lines changed

5 files changed

+86
-2
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,12 @@ def CIR_ConstantOp : CIR_Op<"const", [
413413

414414
template <typename T>
415415
T getValueAttr() { return mlir::dyn_cast<T>(getValue()); }
416+
417+
llvm::APInt getIntValue() {
418+
if (const auto intAttr = getValueAttr<cir::IntAttr>())
419+
return intAttr.getValue();
420+
llvm_unreachable("Expected an IntAttr in ConstantOp");
421+
}
416422
}];
417423

418424
let hasFolder = 1;

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,22 @@ CIRGenFunction::emitTargetBuiltinExpr(unsigned builtinID, const CallExpr *e,
625625
getTarget().getTriple().getArch());
626626
}
627627

628+
mlir::Value CIRGenFunction::emitScalarOrConstFoldImmArg(
629+
const unsigned iceArguments, const unsigned idx, const Expr *argExpr) {
630+
mlir::Value arg = {};
631+
if ((iceArguments & (1 << idx)) == 0) {
632+
arg = emitScalarExpr(argExpr);
633+
} else {
634+
// If this is required to be a constant, constant fold it so that we
635+
// know that the generated intrinsic gets a ConstantInt.
636+
const std::optional<llvm::APSInt> result =
637+
argExpr->getIntegerConstantExpr(getContext());
638+
assert(result && "Expected argument to be a constant");
639+
arg = builder.getConstInt(getLoc(argExpr->getSourceRange()), *result);
640+
}
641+
return arg;
642+
}
643+
628644
/// Given a builtin id for a function like "__builtin_fabsf", return a Function*
629645
/// for "fabsf".
630646
cir::FuncOp CIRGenModule::getBuiltinLibFunction(const FunctionDecl *fd,

clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#include "clang/Basic/Builtins.h"
1717
#include "clang/Basic/TargetBuiltins.h"
1818
#include "clang/CIR/MissingFeatures.h"
19-
#include "llvm/IR/IntrinsicsX86.h"
2019

2120
using namespace clang;
2221
using namespace clang::CIRGen;
@@ -43,6 +42,18 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
4342
// Find out if any arguments are required to be integer constant expressions.
4443
assert(!cir::MissingFeatures::handleBuiltinICEArguments());
4544

45+
llvm::SmallVector<mlir::Value> ops;
46+
47+
// Find out if any arguments are required to be integer constant expressions.
48+
unsigned iceArguments = 0;
49+
ASTContext::GetBuiltinTypeError error;
50+
getContext().GetBuiltinType(builtinID, error, &iceArguments);
51+
assert(error == ASTContext::GE_None && "Should not codegen an error");
52+
53+
for (auto [idx, arg] : llvm::enumerate(e->arguments())) {
54+
ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, idx, arg));
55+
}
56+
4657
switch (builtinID) {
4758
default:
4859
return {};
@@ -63,6 +74,10 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
6374
case X86::BI__builtin_ia32_undef128:
6475
case X86::BI__builtin_ia32_undef256:
6576
case X86::BI__builtin_ia32_undef512:
77+
cgm.errorNYI(e->getSourceRange(),
78+
std::string("unimplemented X86 builtin call: ") +
79+
getContext().BuiltinInfo.getName(builtinID));
80+
return {};
6681
case X86::BI__builtin_ia32_vec_ext_v4hi:
6782
case X86::BI__builtin_ia32_vec_ext_v16qi:
6883
case X86::BI__builtin_ia32_vec_ext_v8hi:
@@ -72,7 +87,24 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
7287
case X86::BI__builtin_ia32_vec_ext_v32qi:
7388
case X86::BI__builtin_ia32_vec_ext_v16hi:
7489
case X86::BI__builtin_ia32_vec_ext_v8si:
75-
case X86::BI__builtin_ia32_vec_ext_v4di:
90+
case X86::BI__builtin_ia32_vec_ext_v4di: {
91+
unsigned NumElts = cast<cir::VectorType>(ops[0].getType()).getSize();
92+
93+
uint64_t index =
94+
ops[1].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue();
95+
96+
index &= NumElts - 1;
97+
98+
auto indexAttr = cir::IntAttr::get(
99+
cir::IntType::get(&getMLIRContext(), 64, false), index);
100+
auto indexVal =
101+
cir::ConstantOp::create(builder, getLoc(e->getExprLoc()), indexAttr);
102+
103+
// These builtins exist so we can ensure the index is an ICE and in range.
104+
// Otherwise we could just do this in the header file.
105+
return cir::VecExtractOp::create(builder, getLoc(e->getExprLoc()), ops[0],
106+
indexVal);
107+
}
76108
case X86::BI__builtin_ia32_vec_set_v4hi:
77109
case X86::BI__builtin_ia32_vec_set_v16qi:
78110
case X86::BI__builtin_ia32_vec_set_v8hi:

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,9 @@ class CIRGenFunction : public CIRGenTypeCache {
16991699
void emitScalarInit(const clang::Expr *init, mlir::Location loc,
17001700
LValue lvalue, bool capturedByInit = false);
17011701

1702+
mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned idx,
1703+
const Expr *argExpr);
1704+
17021705
void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage);
17031706

17041707
void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest,
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse2 -fclangir -emit-cir -o %t.cir -Wall -Werror
2+
// RUN: FileCheck --check-prefixes=CIR-CHECK --input-file=%t.cir %s
3+
// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse2 -fno-signed-char -fclangir -emit-cir -o %t.cir -Wall -Werror
4+
// RUN: FileCheck --check-prefixes=CIR-CHECK --input-file=%t.cir %s
5+
6+
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse2 -fclangir -emit-llvm -o %t.ll -Wall -Werror
7+
// RUN: FileCheck --check-prefixes=LLVM-CHECK --input-file=%t.ll %s
8+
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse2 -fno-signed-char -fclangir -emit-llvm -o %t.ll -Wall -Werror
9+
// RUN: FileCheck --check-prefixes=LLVM-CHECK --input-file=%t.ll %s
10+
11+
// This test mimics clang/test/CodeGen/X86/sse2-builtins.c, which eventually
12+
// CIR shall be able to support fully.
13+
14+
#include <immintrin.h>
15+
16+
// Lowering to pextrw requires optimization.
17+
int test_mm_extract_epi16(__m128i A) {
18+
19+
// CIR-CHECK-LABEL: test_mm_extract_epi16
20+
// CIR-CHECK %{{.*}} = cir.vec.extract %{{.*}}[%{{.*}} : {{!u32i|!u64i}}] : !cir.vector<!s16i x 8>
21+
// CIR-CHECK %{{.*}} = cir.cast integral %{{.*}} : !u16i -> !s32i
22+
23+
// LLVM-CHECK-LABEL: test_mm_extract_epi16
24+
// LLVM-CHECK: extractelement <8 x i16> %{{.*}}, {{i32|i64}} 1
25+
// LLVM-CHECK: zext i16 %{{.*}} to i32
26+
return _mm_extract_epi16(A, 1);
27+
}

0 commit comments

Comments
 (0)