Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,12 @@ def CIR_ConstantOp : CIR_Op<"const", [

template <typename T>
T getValueAttr() { return mlir::dyn_cast<T>(getValue()); }

llvm::APInt getIntValue() {
if (const auto intAttr = getValueAttr<cir::IntAttr>())
return intAttr.getValue();
llvm_unreachable("Expected an IntAttr in ConstantOp");
}
}];

let hasFolder = 1;
Expand Down
16 changes: 16 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,22 @@ CIRGenFunction::emitTargetBuiltinExpr(unsigned builtinID, const CallExpr *e,
getTarget().getTriple().getArch());
}

mlir::Value CIRGenFunction::emitScalarOrConstFoldImmArg(
const unsigned iceArguments, const unsigned idx, const Expr *argExpr) {
mlir::Value arg = {};
if ((iceArguments & (1 << idx)) == 0) {
arg = emitScalarExpr(argExpr);
} else {
// If this is required to be a constant, constant fold it so that we
// know that the generated intrinsic gets a ConstantInt.
const std::optional<llvm::APSInt> result =
argExpr->getIntegerConstantExpr(getContext());
assert(result && "Expected argument to be a constant");
arg = builder.getConstInt(getLoc(argExpr->getSourceRange()), *result);
}
return arg;
}

/// Given a builtin id for a function like "__builtin_fabsf", return a Function*
/// for "fabsf".
cir::FuncOp CIRGenModule::getBuiltinLibFunction(const FunctionDecl *fd,
Expand Down
36 changes: 34 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/IR/IntrinsicsX86.h"

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

llvm::SmallVector<mlir::Value> ops;

// Find out if any arguments are required to be integer constant expressions.
unsigned iceArguments = 0;
ASTContext::GetBuiltinTypeError error;
getContext().GetBuiltinType(builtinID, error, &iceArguments);
assert(error == ASTContext::GE_None && "Should not codegen an error");

for (auto [idx, arg] : llvm::enumerate(e->arguments())) {
ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, idx, arg));
}

switch (builtinID) {
default:
return {};
Expand All @@ -63,6 +74,10 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
case X86::BI__builtin_ia32_undef128:
case X86::BI__builtin_ia32_undef256:
case X86::BI__builtin_ia32_undef512:
cgm.errorNYI(e->getSourceRange(),
std::string("unimplemented X86 builtin call: ") +
getContext().BuiltinInfo.getName(builtinID));
return {};
case X86::BI__builtin_ia32_vec_ext_v4hi:
case X86::BI__builtin_ia32_vec_ext_v16qi:
case X86::BI__builtin_ia32_vec_ext_v8hi:
Expand All @@ -72,7 +87,24 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
case X86::BI__builtin_ia32_vec_ext_v32qi:
case X86::BI__builtin_ia32_vec_ext_v16hi:
case X86::BI__builtin_ia32_vec_ext_v8si:
case X86::BI__builtin_ia32_vec_ext_v4di:
case X86::BI__builtin_ia32_vec_ext_v4di: {
unsigned NumElts = cast<cir::VectorType>(ops[0].getType()).getSize();

uint64_t index =
ops[1].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue();

index &= NumElts - 1;

auto indexAttr = cir::IntAttr::get(
cir::IntType::get(&getMLIRContext(), 64, false), index);
auto indexVal =
cir::ConstantOp::create(builder, getLoc(e->getExprLoc()), indexAttr);

// These builtins exist so we can ensure the index is an ICE and in range.
// Otherwise we could just do this in the header file.
return cir::VecExtractOp::create(builder, getLoc(e->getExprLoc()), ops[0],
indexVal);
}
case X86::BI__builtin_ia32_vec_set_v4hi:
case X86::BI__builtin_ia32_vec_set_v16qi:
case X86::BI__builtin_ia32_vec_set_v8hi:
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1699,6 +1699,9 @@ class CIRGenFunction : public CIRGenTypeCache {
void emitScalarInit(const clang::Expr *init, mlir::Location loc,
LValue lvalue, bool capturedByInit = false);

mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned idx,
const Expr *argExpr);

void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage);

void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest,
Expand Down
27 changes: 27 additions & 0 deletions clang/test/CIR/CodeGen/X86/sse2-builtins.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// 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
// RUN: FileCheck --check-prefixes=CIR-CHECK --input-file=%t.cir %s
// 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
// RUN: FileCheck --check-prefixes=CIR-CHECK --input-file=%t.cir %s

// 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
// RUN: FileCheck --check-prefixes=LLVM-CHECK --input-file=%t.ll %s
// 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
// RUN: FileCheck --check-prefixes=LLVM-CHECK --input-file=%t.ll %s

// This test mimics clang/test/CodeGen/X86/sse2-builtins.c, which eventually
// CIR shall be able to support fully.

#include <immintrin.h>

// Lowering to pextrw requires optimization.
int test_mm_extract_epi16(__m128i A) {

// CIR-CHECK-LABEL: test_mm_extract_epi16
// CIR-CHECK %{{.*}} = cir.vec.extract %{{.*}}[%{{.*}} : {{!u32i|!u64i}}] : !cir.vector<!s16i x 8>
// CIR-CHECK %{{.*}} = cir.cast integral %{{.*}} : !u16i -> !s32i

// LLVM-CHECK-LABEL: test_mm_extract_epi16
// LLVM-CHECK: extractelement <8 x i16> %{{.*}}, {{i32|i64}} 1
// LLVM-CHECK: zext i16 %{{.*}} to i32
return _mm_extract_epi16(A, 1);
}
Loading