diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11943,7 +11943,7 @@ // type checking for sizeless vector binary operators. QualType CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc, + SourceLocation Loc, bool IsCompAssign, ArithConvKind OperationKind); /// Type checking for matrix binary operators. diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -32,6 +32,7 @@ #include "llvm/IR/CFG.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" #include "llvm/IR/FixedPointBuilder.h" #include "llvm/IR/Function.h" #include "llvm/IR/GetElementPtrTypeIterator.h" @@ -40,6 +41,7 @@ #include "llvm/IR/IntrinsicsPowerPC.h" #include "llvm/IR/MatrixBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/Support/TypeSize.h" #include using namespace clang; @@ -2329,9 +2331,10 @@ } case CK_VectorSplat: { llvm::Type *DstTy = ConvertType(DestTy); - Value *Elt = Visit(const_cast(E)); + Value *Elt = Visit(const_cast(E)); // Splat the element across to all elements - unsigned NumElements = cast(DstTy)->getNumElements(); + llvm::ElementCount NumElements = + cast(DstTy)->getElementCount(); return Builder.CreateVectorSplat(NumElements, Elt, "splat"); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -10465,7 +10465,17 @@ QualType Sema::CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, + bool IsCompAssign, ArithConvKind OperationKind) { + if (!IsCompAssign) { + LHS = DefaultFunctionArrayLvalueConversion(LHS.get()); + if (LHS.isInvalid()) + return QualType(); + } + RHS = DefaultFunctionArrayLvalueConversion(RHS.get()); + if (RHS.isInvalid()) + return QualType(); + QualType LHSType = LHS.get()->getType().getUnqualifiedType(); QualType RHSType = RHS.get()->getType().getUnqualifiedType(); @@ -10483,6 +10493,26 @@ if (Context.hasSameType(LHSType, RHSType)) return LHSType; + auto tryScalableVectorConvert = [this](ExprResult *Src, QualType SrcType, + QualType DestType) { + const QualType DestBaseType = DestType->getSveEltType(Context); + if (DestBaseType->getUnqualifiedDesugaredType() == + SrcType->getUnqualifiedDesugaredType()) { + unsigned DiagID = diag::err_typecheck_invalid_operands; + if (!tryVectorConvertAndSplat(*this, Src, SrcType, DestBaseType, DestType, + DiagID)) + return DestType; + } + return QualType(); + }; + + if (LHSType->isVLSTBuiltinType() && !RHSType->isVLSTBuiltinType()) + return tryScalableVectorConvert(&RHS, RHSType, LHSType); + + if (RHSType->isVLSTBuiltinType() && !LHSType->isVLSTBuiltinType()) + return tryScalableVectorConvert((IsCompAssign ? nullptr : &LHS), LHSType, + RHSType); + Diag(Loc, DiagID) << LHSType << RHSType << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return QualType(); @@ -10602,7 +10632,8 @@ /*AllowBooleanOperation*/ false, /*ReportInvalid*/ true); if (LHSTy->isVLSTBuiltinType() || RHSTy->isVLSTBuiltinType()) - return CheckSizelessVectorOperands(LHS, RHS, Loc, ACK_Arithmetic); + return CheckSizelessVectorOperands(LHS, RHS, Loc, IsCompAssign, + ACK_Arithmetic); if (!IsDiv && (LHSTy->isConstantMatrixType() || RHSTy->isConstantMatrixType())) return CheckMatrixMultiplyOperands(LHS, RHS, Loc, IsCompAssign); @@ -10642,17 +10673,12 @@ return InvalidOperands(Loc, LHS, RHS); } - if (LHS.get()->getType()->isVLSTBuiltinType() && + if (LHS.get()->getType()->isVLSTBuiltinType() || RHS.get()->getType()->isVLSTBuiltinType()) { - if (LHS.get() - ->getType() - ->getSveEltType(Context) - ->hasIntegerRepresentation() && - RHS.get() - ->getType() - ->getSveEltType(Context) - ->hasIntegerRepresentation()) - return CheckSizelessVectorOperands(LHS, RHS, Loc, ACK_Arithmetic); + if (LHS.get()->getType()->hasIntegerRepresentation() && + RHS.get()->getType()->hasIntegerRepresentation()) + return CheckSizelessVectorOperands(LHS, RHS, Loc, IsCompAssign, + ACK_Arithmetic); return InvalidOperands(Loc, LHS, RHS); } @@ -10967,7 +10993,7 @@ if (LHS.get()->getType()->isVLSTBuiltinType() || RHS.get()->getType()->isVLSTBuiltinType()) { QualType compType = - CheckSizelessVectorOperands(LHS, RHS, Loc, ACK_Arithmetic); + CheckSizelessVectorOperands(LHS, RHS, Loc, CompLHSTy, ACK_Arithmetic); if (CompLHSTy) *CompLHSTy = compType; return compType; @@ -11082,7 +11108,7 @@ if (LHS.get()->getType()->isVLSTBuiltinType() || RHS.get()->getType()->isVLSTBuiltinType()) { QualType compType = - CheckSizelessVectorOperands(LHS, RHS, Loc, ACK_Arithmetic); + CheckSizelessVectorOperands(LHS, RHS, Loc, CompLHSTy, ACK_Arithmetic); if (CompLHSTy) *CompLHSTy = compType; return compType; @@ -12897,7 +12923,8 @@ RHS.get()->getType()->isVLSTBuiltinType()) { if (LHS.get()->getType()->hasIntegerRepresentation() && RHS.get()->getType()->hasIntegerRepresentation()) - return CheckSizelessVectorOperands(LHS, RHS, Loc, ACK_BitwiseOp); + return CheckSizelessVectorOperands(LHS, RHS, Loc, IsCompAssign, + ACK_BitwiseOp); return InvalidOperands(Loc, LHS, RHS); } @@ -12905,7 +12932,8 @@ RHS.get()->getType()->isVLSTBuiltinType()) { if (LHS.get()->getType()->hasIntegerRepresentation() && RHS.get()->getType()->hasIntegerRepresentation()) - return CheckSizelessVectorOperands(LHS, RHS, Loc, ACK_BitwiseOp); + return CheckSizelessVectorOperands(LHS, RHS, Loc, IsCompAssign, + ACK_BitwiseOp); return InvalidOperands(Loc, LHS, RHS); } diff --git a/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c b/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c --- a/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c +++ b/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c @@ -207,6 +207,121 @@ return a += b; } +// CHECK-LABEL: @add_scalar_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[ADD]] +// +svint8_t add_scalar_i8(svint8_t a, int8_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[ADD]] +// +svint16_t add_scalar_i16(svint16_t a, int16_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[ADD]] +// +svint32_t add_scalar_i32(svint32_t a, int32_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[ADD]] +// +svint64_t add_scalar_i64(svint64_t a, int64_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[ADD]] +// +svuint8_t add_scalar_u8(svuint8_t a, uint8_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[ADD]] +// +svuint16_t add_scalar_u16(svuint16_t a, uint16_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[ADD]] +// +svuint32_t add_scalar_u32(svuint32_t a, uint32_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[ADD:%.*]] = add [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[ADD]] +// +svuint64_t add_scalar_u64(svuint64_t a, uint64_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = fadd [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: ret [[ADD]] +// +svfloat16_t add_scalar_f16(svfloat16_t a, svfloat16_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = fadd [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: ret [[ADD]] +// +svfloat32_t add_scalar_f32(svfloat32_t a, svfloat32_t b) { + return a + b; +} + +// CHECK-LABEL: @add_scalar_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ADD:%.*]] = fadd [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: ret [[ADD]] +// +svfloat64_t add_scalar_f64(svfloat64_t a, svfloat64_t b) { + return a + b; +} + // SUBTRACTION // CHECK-LABEL: @sub_i8( @@ -407,6 +522,121 @@ return a - b; } +// CHECK-LABEL: @sub_scalar_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[SUB]] +// +svint8_t sub_scalar_i8(svint8_t a, int8_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[SUB]] +// +svint16_t sub_scalar_i16(svint16_t a, int16_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[SUB]] +// +svint32_t sub_scalar_i32(svint32_t a, int32_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[SUB]] +// +svint64_t sub_scalar_i64(svint64_t a, int64_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[SUB]] +// +svuint8_t sub_scalar_u8(svuint8_t a, uint8_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[SUB]] +// +svuint16_t sub_scalar_u16(svuint16_t a, uint16_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[SUB]] +// +svuint32_t sub_scalar_u32(svuint32_t a, uint32_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[SUB:%.*]] = sub [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[SUB]] +// +svuint64_t sub_scalar_u64(svuint64_t a, uint64_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SUB:%.*]] = fsub [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: ret [[SUB]] +// +svfloat16_t sub_scalar_f16(svfloat16_t a, svfloat16_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SUB:%.*]] = fsub [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: ret [[SUB]] +// +svfloat32_t sub_scalar_f32(svfloat32_t a, svfloat32_t b) { + return a - b; +} + +// CHECK-LABEL: @sub_scalar_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SUB:%.*]] = fsub [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: ret [[SUB]] +// +svfloat64_t sub_scalar_f64(svfloat64_t a, svfloat64_t b) { + return a - b; +} + // MULTIPLICATION // CHECK-LABEL: @mul_i8( @@ -607,6 +837,121 @@ return a * b; } +// CHECK-LABEL: @mul_scalar_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[MUL]] +// +svint8_t mul_scalar_i8(svint8_t a, int8_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[MUL]] +// +svint16_t mul_scalar_i16(svint16_t a, int16_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[MUL]] +// +svint32_t mul_scalar_i32(svint32_t a, int32_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[MUL]] +// +svint64_t mul_scalar_i64(svint64_t a, int64_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[MUL]] +// +svuint8_t mul_scalar_u8(svuint8_t a, uint8_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[MUL]] +// +svuint16_t mul_scalar_u16(svuint16_t a, uint16_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[MUL]] +// +svuint32_t mul_scalar_u32(svuint32_t a, uint32_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[MUL:%.*]] = mul [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[MUL]] +// +svuint64_t mul_scalar_u64(svuint64_t a, uint64_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[MUL:%.*]] = fmul [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: ret [[MUL]] +// +svfloat16_t mul_scalar_f16(svfloat16_t a, svfloat16_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[MUL:%.*]] = fmul [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: ret [[MUL]] +// +svfloat32_t mul_scalar_f32(svfloat32_t a, svfloat32_t b) { + return a * b; +} + +// CHECK-LABEL: @mul_scalar_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[MUL:%.*]] = fmul [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: ret [[MUL]] +// +svfloat64_t mul_scalar_f64(svfloat64_t a, svfloat64_t b) { + return a * b; +} + // DIVISION // CHECK-LABEL: @div_i8( @@ -807,6 +1152,121 @@ return a / b; } +// CHECK-LABEL: @div_scalar_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = sdiv [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[DIV]] +// +svint8_t div_scalar_i8(svint8_t a, int8_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = sdiv [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[DIV]] +// +svint16_t div_scalar_i16(svint16_t a, int16_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = sdiv [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[DIV]] +// +svint32_t div_scalar_i32(svint32_t a, int32_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = sdiv [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[DIV]] +// +svint64_t div_scalar_i64(svint64_t a, int64_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = udiv [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[DIV]] +// +svuint8_t div_scalar_u8(svuint8_t a, uint8_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = udiv [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[DIV]] +// +svuint16_t div_scalar_u16(svuint16_t a, uint16_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = udiv [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[DIV]] +// +svuint32_t div_scalar_u32(svuint32_t a, uint32_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[DIV:%.*]] = udiv [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[DIV]] +// +svuint64_t div_scalar_u64(svuint64_t a, uint64_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DIV:%.*]] = fdiv [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: ret [[DIV]] +// +svfloat16_t div_scalar_f16(svfloat16_t a, svfloat16_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DIV:%.*]] = fdiv [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: ret [[DIV]] +// +svfloat32_t div_scalar_f32(svfloat32_t a, svfloat32_t b) { + return a / b; +} + +// CHECK-LABEL: @div_scalar_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DIV:%.*]] = fdiv [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: ret [[DIV]] +// +svfloat64_t div_scalar_f64(svfloat64_t a, svfloat64_t b) { + return a / b; +} + // REMAINDER // CHECK-LABEL: @rem_i8( @@ -952,3 +1412,91 @@ svuint64_t rem_inplace_u64(svuint64_t a, svuint64_t b) { return a % b; } + +// CHECK-LABEL: @rem_scalar_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = srem [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[REM]] +// +svint8_t rem_scalar_i8(svint8_t a, int8_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = srem [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[REM]] +// +svint16_t rem_scalar_i16(svint16_t a, int16_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = srem [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[REM]] +// +svint32_t rem_scalar_i32(svint32_t a, int32_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = srem [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[REM]] +// +svint64_t rem_scalar_i64(svint64_t a, int64_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i8 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = urem [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[REM]] +// +svuint8_t rem_scalar_u8(svuint8_t a, uint8_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i16 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = urem [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[REM]] +// +svuint16_t rem_scalar_u16(svuint16_t a, uint16_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i32 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = urem [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[REM]] +// +svuint32_t rem_scalar_u32(svuint32_t a, uint32_t b) { + return a % b; +} + +// CHECK-LABEL: @rem_scalar_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement poison, i64 [[B:%.*]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector [[SPLAT_SPLATINSERT]], poison, zeroinitializer +// CHECK-NEXT: [[REM:%.*]] = urem [[A:%.*]], [[SPLAT_SPLAT]] +// CHECK-NEXT: ret [[REM]] +// +svuint64_t rem_scalar_u64(svuint64_t a, uint64_t b) { + return a % b; +}