Skip to content
Merged
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
3 changes: 0 additions & 3 deletions clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,6 @@ struct MissingFeatures {
static bool volatileTypes() { return false; }
static bool syncScopeID() { return false; }

// AArch64 Neon builtin related.
static bool buildNeonShiftVector() { return false; }

// ABIInfo queries.
static bool useTargetLoweringABIInfo() { return false; }

Expand Down
88 changes: 53 additions & 35 deletions clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2160,6 +2160,43 @@ static mlir::Value buildArmLdrexNon128Intrinsic(unsigned int builtinID,
}
}

/// Given a vector of unsigned int type `vecTy`, return a vector type of
/// signed int type with the same element type width and vector size.
static mlir::cir::VectorType getSignedVectorType(CIRGenBuilderTy &builder,
mlir::cir::VectorType vecTy) {
auto elemTy = mlir::cast<mlir::cir::IntType>(vecTy.getEltType());
elemTy = builder.getSIntNTy(elemTy.getWidth());
return mlir::cir::VectorType::get(builder.getContext(), elemTy,
vecTy.getSize());
}

/// Get integer from a mlir::Value that is an int constant or a constant op.
static int64_t getIntValueFromConstOp(mlir::Value val) {
auto constOp = mlir::cast<mlir::cir::ConstantOp>(val.getDefiningOp());
return (mlir::cast<mlir::cir::IntAttr>(constOp.getValue()))
.getValue()
.getSExtValue();
}

/// Build a constant shift amount vector of `vecTy` to shift a vector
/// Here `shitfVal` is a constant integer that will be splated into a
/// a const vector of `vecTy` which is the return of this function
static mlir::Value buildNeonShiftVector(CIRGenBuilderTy &builder,
mlir::Value shiftVal,
mlir::cir::VectorType vecTy,
mlir::Location loc, bool neg) {
int shiftAmt = getIntValueFromConstOp(shiftVal);
if (neg)
shiftAmt = -shiftAmt;
llvm::SmallVector<mlir::Attribute> vecAttr{
vecTy.getSize(),
// ConstVectorAttr requires cir::IntAttr
mlir::cir::IntAttr::get(vecTy.getEltType(), shiftAmt)};
mlir::cir::ConstVectorAttr constVecAttr = mlir::cir::ConstVectorAttr::get(
vecTy, mlir::ArrayAttr::get(builder.getContext(), vecAttr));
return builder.create<mlir::cir::ConstantOp>(loc, vecTy, constVecAttr);
}

mlir::Value buildNeonCall(CIRGenBuilderTy &builder,
llvm::SmallVector<mlir::Type> argTypes,
llvm::SmallVectorImpl<mlir::Value> &args,
Expand All @@ -2172,38 +2209,27 @@ mlir::Value buildNeonCall(CIRGenBuilderTy &builder,
assert(!MissingFeatures::buildConstrainedFPCall());
if (isConstrainedFPIntrinsic)
llvm_unreachable("isConstrainedFPIntrinsic NYI");
// TODO: Remove the following unreachable and call it in the loop once
// there is an implementation of buildNeonShiftVector
if (shift > 0)
llvm_unreachable("Argument shift NYI");

for (unsigned j = 0; j < argTypes.size(); ++j) {
if (isConstrainedFPIntrinsic) {
assert(!MissingFeatures::buildConstrainedFPCall());
}
if (shift > 0 && shift == j) {
assert(!MissingFeatures::buildNeonShiftVector());
args[j] = buildNeonShiftVector(
builder, args[j], mlir::cast<mlir::cir::VectorType>(argTypes[j]), loc,
rightshift);
} else {
args[j] = builder.createBitcast(args[j], argTypes[j]);
}
}
if (isConstrainedFPIntrinsic) {
assert(!MissingFeatures::buildConstrainedFPCall());
return nullptr;
} else {
return builder
.create<mlir::cir::IntrinsicCallOp>(
loc, builder.getStringAttr(intrinsicName), funcResTy, args)
.getResult();
}
}

/// Get integer from a mlir::Value that is an int constant or a constant op.
static int64_t getIntValueFromConstOp(mlir::Value val) {
auto constOp = mlir::cast<mlir::cir::ConstantOp>(val.getDefiningOp());
return (mlir::cast<mlir::cir::IntAttr>(constOp.getValue()))
.getValue()
.getSExtValue();
return builder
.create<mlir::cir::IntrinsicCallOp>(
loc, builder.getStringAttr(intrinsicName), funcResTy, args)
.getResult();
}

/// This function `buildCommonNeonCallPattern0` implements a common way
Expand All @@ -2224,23 +2250,6 @@ buildCommonNeonCallPattern0(CIRGenFunction &cgf, llvm::StringRef intrincsName,
return builder.createBitcast(res, resultType);
}

/// Build a constant shift amount vector of `vecTy` to shift a vector
/// Here `shitfVal` is a constant integer that will be splated into a
/// a const vector of `vecTy` which is the return of this function
static mlir::Value buildNeonShiftVector(CIRGenBuilderTy &builder,
mlir::Value shiftVal,
mlir::cir::VectorType vecTy,
mlir::Location loc, bool neg) {
int shiftAmt = getIntValueFromConstOp(shiftVal);
llvm::SmallVector<mlir::Attribute> vecAttr{
vecTy.getSize(),
// ConstVectorAttr requires cir::IntAttr
mlir::cir::IntAttr::get(vecTy.getEltType(), shiftAmt)};
mlir::cir::ConstVectorAttr constVecAttr = mlir::cir::ConstVectorAttr::get(
vecTy, mlir::ArrayAttr::get(builder.getContext(), vecAttr));
return builder.create<mlir::cir::ConstantOp>(loc, vecTy, constVecAttr);
}

/// Build ShiftOp of vector type whose shift amount is a vector built
/// from a constant integer using `buildNeonShiftVector` function
static mlir::Value buildCommonNeonShift(CIRGenBuilderTy &builder,
Expand Down Expand Up @@ -2338,6 +2347,15 @@ mlir::Value CIRGenFunction::buildCommonNeonBuiltinExpr(
: "llvm.aarch64.neon.sqrdmulh.lane",
resTy, getLoc(e->getExprLoc()));
}
case NEON::BI__builtin_neon_vrshr_n_v:
case NEON::BI__builtin_neon_vrshrq_n_v: {
return buildNeonCall(
builder, {vTy, isUnsigned ? getSignedVectorType(builder, vTy) : vTy},
ops, isUnsigned ? "llvm.aarch64.neon.urshl" : "llvm.aarch64.neon.srshl",
vTy, getLoc(e->getExprLoc()), false, /* not fp constrained op*/
1, /* second arg is shift amount */
true /* rightshift */);
}
case NEON::BI__builtin_neon_vshl_n_v:
case NEON::BI__builtin_neon_vshlq_n_v: {
mlir::Location loc = getLoc(e->getExprLoc());
Expand Down
Loading