Index: clang/include/clang/Basic/TargetBuiltins.h =================================================================== --- clang/include/clang/Basic/TargetBuiltins.h +++ clang/include/clang/Basic/TargetBuiltins.h @@ -233,6 +233,7 @@ bool isStructStore() const { return Flags & IsStructStore; } bool isZExtReturn() const { return Flags & IsZExtReturn; } bool isNoAuto() const { return Flags & NoAuto; } + bool isNotOverloaded() const { return Flags & NoOverloadTy; } uint64_t getBits() const { return Flags; } bool isFlagSet(uint64_t Flag) const { return Flags & Flag; } Index: clang/include/clang/Basic/arm_sve.td =================================================================== --- clang/include/clang/Basic/arm_sve.td +++ clang/include/clang/Basic/arm_sve.td @@ -167,6 +167,7 @@ def IsStructStore : FlagType<0x00040000>; def IsZExtReturn : FlagType<0x00080000>; // Return value is sign-extend by default def NoAuto : FlagType<0x00100000>; +def NoOverloadTy : FlagType<0x00200000>; // These must be kept in sync with the flags in include/clang/Basic/TargetBuiltins.h class ImmCheckType { @@ -392,6 +393,7 @@ def SVCMLA_LANE : SInst<"svcmla_lane[_{d}]", "ddddii", "hf", MergeNone, "aarch64_sve_fcmla_lane", [], [ImmCheck<3, ImmCheckLaneIndexCompRotate, 2>, ImmCheck<4, ImmCheckComplexRotAll90>]>; + def SVCADD_M : SInst<"svcadd[_{d}]", "dPddi", "hfd", MergeOp1, "aarch64_sve_fcadd", [], [ImmCheck<3, ImmCheckComplexRot90_270>]>; def SVCMLA_M : SInst<"svcmla[_{d}]", "dPdddi", "hfd", MergeOp1, "aarch64_sve_fcmla", [], [ImmCheck<4, ImmCheckComplexRotAll90>]>; @@ -400,6 +402,12 @@ def SVQDECH_S : SInst<"svqdech_pat[_{d}]", "ddIi", "s", MergeNone, "aarch64_sve_sqdech", [], [ImmCheck<2, ImmCheck1_16>]>; def SVQDECH_U : SInst<"svqdech_pat[_{d}]", "ddIi", "Us", MergeNone, "aarch64_sve_uqdech", [], [ImmCheck<2, ImmCheck1_16>]>; + +//////////////////////////////////////////////////////////////////////////////// +// Predicate creation + +def SVPFALSE : SInst<"svpfalse[_b]", "P", "", MergeNone, "", [NoOverloadTy]>; + //////////////////////////////////////////////////////////////////////////////// // Integer arithmetic def SVDOT_LANE_S : SInst<"svdot_lane[_{d}]", "ddqqi", "il", MergeNone, "aarch64_sve_sdot_lane", [], [ImmCheck<3, ImmCheckLaneIndexDot, 2>]>; Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -7655,14 +7655,25 @@ Ops[1] = Builder.CreateSelect(Ops[0], Ops[1], SplatZero); } - Function *F = CGM.getIntrinsic(Builtin->LLVMIntrinsic, OverloadedTy); + Function *F = TypeFlags.isNotOverloaded() + ? CGM.getIntrinsic(Builtin->LLVMIntrinsic) + : CGM.getIntrinsic(Builtin->LLVMIntrinsic, OverloadedTy); Value *Call = Builder.CreateCall(F, Ops); - return Call; + + // Predicate results must be converted to svbool_t. + if (auto PredTy = dyn_cast(Call->getType())) + if (PredTy->getScalarType()->isIntegerTy(1)) + Call = EmitSVEPredicateCast(Call, cast(Ty)); + + return Call; } switch (BuiltinID) { default: return nullptr; + case SVE::BI__builtin_sve_svpfalse_b: + return ConstantInt::getFalse(Ty); + case SVE::BI__builtin_sve_svwhilele_b8_s32: case SVE::BI__builtin_sve_svwhilele_b8_s64: case SVE::BI__builtin_sve_svwhilele_b8_u32: Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_pfalse.c =================================================================== --- /dev/null +++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_pfalse.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s + +#include + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +svbool_t test_svpfalse_b() +{ + // CHECK-LABEL: test_svpfalse_b + // CHECK: ret zeroinitializer + return SVE_ACLE_FUNC(svpfalse,_b,,)(); +} Index: clang/utils/TableGen/SveEmitter.cpp =================================================================== --- clang/utils/TableGen/SveEmitter.cpp +++ clang/utils/TableGen/SveEmitter.cpp @@ -261,6 +261,14 @@ llvm_unreachable("Unsupported imm check"); } + /// Returns the enum value for the flag type + uint64_t getEnumValueForFlag(StringRef C) const { + auto Res = FlagTypes.find(C); + if (Res != FlagTypes.end()) + return Res->getValue(); + llvm_unreachable("Unsupported flag"); + } + // Returns the SVETypeFlags for a given value and mask. uint64_t encodeFlag(uint64_t V, StringRef MaskName) const { auto It = FlagTypes.find(MaskName); @@ -844,6 +852,13 @@ for (auto FlagRec : FlagsList) Flags |= FlagRec->getValueAsInt("Value"); + // Create a dummy TypeSpec for non-overloaded builtins. + if (Types.empty()) { + assert((Flags & getEnumValueForFlag("NoOverloadTy")) && + "Expect TypeSpec for overloaded builtin!"); + Types = "i"; + } + // Extract type specs from string SmallVector TypeSpecs; TypeSpec Acc;