Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 4 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,10 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return getConstantInt(loc, getUInt32Ty(), c);
}
cir::ConstantOp getSInt64(uint64_t c, mlir::Location loc) {
cir::IntType sInt64Ty = getSInt64Ty();
return cir::ConstantOp::create(*this, loc, cir::IntAttr::get(sInt64Ty, c));
return getConstantInt(loc, getSInt64Ty(), c);
}
cir::ConstantOp getUInt64(uint64_t c, mlir::Location loc) {
return getConstantInt(loc, getUInt64Ty(), c);
}

mlir::Value createNeg(mlir::Value value) {
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
33 changes: 31 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,17 @@ 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 +73,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 +86,22 @@ 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;

cir::ConstantOp indexVal =
builder.getUInt64(index, getLoc(e->getExprLoc()));

// 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
36 changes: 36 additions & 0 deletions clang/test/CIR/CodeGen/X86/sse2-builtins.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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 --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 --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 --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 --input-file=%t.ll %s

// RUN: FileCheck --check-prefixes=OGCG --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 -emit-llvm -o %t.ll -Wall -Werror
// RUN: FileCheck --check-prefixes=OGCG --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-LABEL: test_mm_extract_epi16
// CIR %{{.*}} = cir.vec.extract %{{.*}}[%{{.*}} : {{!u32i|!u64i}}] : !cir.vector<!s16i x 8>
// CIR %{{.*}} = cir.cast integral %{{.*}} : !u16i -> !s32i

// LLVM-LABEL: test_mm_extract_epi16
// LLVM: extractelement <8 x i16> %{{.*}}, {{i32|i64}} 1
// LLVM: zext i16 %{{.*}} to i32

// OGCG-LABEL: test_mm_extract_epi16
// OGCG: extractelement <8 x i16> %{{.*}}, {{i32|i64}} 1
// OGCG: zext i16 %{{.*}} to i32

return _mm_extract_epi16(A, 1);
}
Loading