Skip to content
Open
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
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/arm_mve.td
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ foreach half = [ "b", "t" ] in {
} // params = [f16], pnt = PNT_None
} // loop over half = "b", "t"

multiclass float_int_conversions<Type FScalar, Type IScalar, IRBuilderBase ftoi, IRBuilderBase itof> {
multiclass float_int_conversions<Type FScalar, Type IScalar, Builder ftoi, Builder itof> {
defvar FVector = VecOf<FScalar>;
defvar IVector = VecOf<IScalar>;

Expand Down
20 changes: 14 additions & 6 deletions clang/include/clang/Basic/arm_mve_defs.td
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ def fcmp_ule: IRBuilder<"CreateFCmpULE">;
def splat: CGHelperFn<"ARMMVEVectorSplat">;
def select: IRBuilder<"CreateSelect">;
def fneg: IRBuilder<"CreateFNeg">;
def sitofp: IRBuilder<"CreateSIToFP">;
def uitofp: IRBuilder<"CreateUIToFP">;
def fptosi: IRBuilder<"CreateFPToSI">;
def fptoui: IRBuilder<"CreateFPToUI">;
def sitofp_node: IRBuilder<"CreateSIToFP">;
def uitofp_node: IRBuilder<"CreateUIToFP">;
def fptosi_node: IRBuilder<"CreateFPToSI">;
def fptoui_node: IRBuilder<"CreateFPToUI">;
def vrev: CGHelperFn<"ARMMVEVectorElementReverse"> {
let special_params = [IRBuilderIntParam<1, "unsigned">];
}
Expand Down Expand Up @@ -215,9 +215,9 @@ def bitsize;

// strictFPAlt allows a node to have different code generation under strict-fp.
// TODO: The standard node can be IRBuilderBase or IRIntBase.
class strictFPAlt<Builder standard_, IRIntBase strictfp_> : Builder {
class strictFPAlt<Builder standard_, Builder strictfp_> : Builder {
Builder standard = standard_;
IRIntBase strictfp = strictfp_;
Builder strictfp = strictfp_;
}

// If you put CustomCodegen<"foo"> in an intrinsic's codegen field, it
Expand Down Expand Up @@ -593,6 +593,14 @@ def fminnm : strictFPAlt<IRIntBase<"minnum", [Vector]>,
IRInt<"vminnm", [Vector]>>;
def fmaxnm : strictFPAlt<IRIntBase<"maxnum", [Vector]>,
IRInt<"vmaxnm", [Vector]>>;
def sitofp: strictFPAlt<sitofp_node,
CGFHelperFn<"ARMMVECreateSIToFP">>;
def uitofp: strictFPAlt<uitofp_node,
CGFHelperFn<"ARMMVECreateUIToFP">>;
def fptosi: strictFPAlt<fptosi_node,
CGFHelperFn<"ARMMVECreateFPToSI">>;
def fptoui: strictFPAlt<fptoui_node,
CGFHelperFn<"ARMMVECreateFPToUI">>;

// -----------------------------------------------------------------------------
// Convenience lists of parameter types. 'T' is just a container record, so you
Expand Down
32 changes: 32 additions & 0 deletions clang/lib/CodeGen/TargetBuiltins/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3512,6 +3512,38 @@ static llvm::Value *ARMMVEVectorElementReverse(CGBuilderTy &Builder,
return Builder.CreateShuffleVector(V, Indices);
}

static llvm::Value *ARMMVECreateSIToFP(CGBuilderTy &Builder,
CodeGenFunction *CGF, llvm::Value *V,
llvm::Type *Ty) {
return Builder.CreateCall(
CGF->CGM.getIntrinsic(Intrinsic::arm_mve_vcvt_fp_int, {Ty, V->getType()}),
{V, llvm::ConstantInt::get(Builder.getInt32Ty(), 0)});
}

static llvm::Value *ARMMVECreateUIToFP(CGBuilderTy &Builder,
CodeGenFunction *CGF, llvm::Value *V,
llvm::Type *Ty) {
return Builder.CreateCall(
CGF->CGM.getIntrinsic(Intrinsic::arm_mve_vcvt_fp_int, {Ty, V->getType()}),
{V, llvm::ConstantInt::get(Builder.getInt32Ty(), 1)});
}

static llvm::Value *ARMMVECreateFPToSI(CGBuilderTy &Builder,
CodeGenFunction *CGF, llvm::Value *V,
llvm::Type *Ty) {
return Builder.CreateCall(
CGF->CGM.getIntrinsic(Intrinsic::arm_mve_vcvt_int_fp, {Ty, V->getType()}),
{V, llvm::ConstantInt::get(Builder.getInt32Ty(), 0)});
}

static llvm::Value *ARMMVECreateFPToUI(CGBuilderTy &Builder,
CodeGenFunction *CGF, llvm::Value *V,
llvm::Type *Ty) {
return Builder.CreateCall(
CGF->CGM.getIntrinsic(Intrinsic::arm_mve_vcvt_int_fp, {Ty, V->getType()}),
{V, llvm::ConstantInt::get(Builder.getInt32Ty(), 1)});
}

Value *CodeGenFunction::EmitARMMVEBuiltinExpr(unsigned BuiltinID,
const CallExpr *E,
ReturnValueSlot ReturnValue,
Expand Down
958 changes: 658 additions & 300 deletions clang/test/CodeGen/arm-mve-intrinsics/vcvt.c

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions clang/utils/TableGen/MveEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1294,10 +1294,13 @@ Result::Ptr EmitterBase::getCodeForDag(const DagInit *D,
return GenIRIntBase(Op);
} else if (Op->isSubClassOf("strictFPAlt")) {
auto StardardBuilder = Op->getValueAsDef("standard");
Result::Ptr Standard = StardardBuilder->isSubClassOf("IRBuilder")
Result::Ptr Standard = StardardBuilder->isSubClassOf("IRBuilderBase")
? GenIRBuilderBase(StardardBuilder)
: GenIRIntBase(StardardBuilder);
Result::Ptr StrictFp = GenIRIntBase(Op->getValueAsDef("strictfp"));
auto StrictBuilder = Op->getValueAsDef("strictfp");
Result::Ptr StrictFp = StrictBuilder->isSubClassOf("IRBuilderBase")
? GenIRBuilderBase(StrictBuilder)
: GenIRIntBase(StrictBuilder);
return std::make_shared<StrictFpAltResult>(Standard, StrictFp);
} else {
PrintFatalError("Unsupported dag node " + Op->getName());
Expand Down
6 changes: 6 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsARM.td
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,12 @@ defm int_arm_mve_vcvt_fix: MVEMXPredicated<
[llvm_anyvector_ty /* input vector */, llvm_i32_ty /* scale */],
LLVMMatchType<0>, llvm_anyvector_ty>;

def int_arm_mve_vcvt_fp_int: DefaultAttrsIntrinsic<
[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_i32_ty /* unsigned */],
[IntrNoMem]>;
def int_arm_mve_vcvt_int_fp: DefaultAttrsIntrinsic<
[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_i32_ty /* unsigned */],
[IntrNoMem]>;
def int_arm_mve_vcvt_fp_int_predicated: DefaultAttrsIntrinsic<
[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_i32_ty /* unsigned */,
llvm_anyvector_ty /* predicate */, LLVMMatchType<0> /* inactive */],
Expand Down
20 changes: 11 additions & 9 deletions llvm/lib/Target/ARM/ARMInstrMVE.td
Original file line number Diff line number Diff line change
Expand Up @@ -4045,7 +4045,7 @@ class MVE_VCVT_fp_int<string suffix, bits<2> size, bit toint, bit unsigned,
}

multiclass MVE_VCVT_fp_int_m<MVEVectorVTInfo Dest, MVEVectorVTInfo Src,
SDNode unpred_op> {
SDNode unpred_op, SDPatternOperator unpred_intrinsic> {
defvar Unsigned = !or(!eq(Dest.SuffixLetter,"u"), !eq(Src.SuffixLetter,"u"));
defvar ToInt = !eq(Src.SuffixLetter,"f");

Expand All @@ -4056,6 +4056,8 @@ multiclass MVE_VCVT_fp_int_m<MVEVectorVTInfo Dest, MVEVectorVTInfo Src,
let Predicates = [HasMVEFloat] in {
def : Pat<(Dest.Vec (unpred_op (Src.Vec MQPR:$src))),
(Dest.Vec (Inst (Src.Vec MQPR:$src)))>;
def : Pat<(Dest.Vec (unpred_intrinsic (Src.Vec MQPR:$src), (i32 Unsigned))),
(Dest.Vec (Inst (Src.Vec MQPR:$src)))>;
def : Pat<(Dest.Vec (int_arm_mve_vcvt_fp_int_predicated
(Src.Vec MQPR:$src), (i32 Unsigned),
(Src.Pred VCCR:$mask), (Dest.Vec MQPR:$inactive))),
Expand All @@ -4066,15 +4068,15 @@ multiclass MVE_VCVT_fp_int_m<MVEVectorVTInfo Dest, MVEVectorVTInfo Src,
}
// The unsuffixed VCVT for float->int implicitly rounds toward zero,
// which I reflect here in the llvm instruction names
defm MVE_VCVTs16f16z : MVE_VCVT_fp_int_m<MVE_v8s16, MVE_v8f16, fp_to_sint>;
defm MVE_VCVTu16f16z : MVE_VCVT_fp_int_m<MVE_v8u16, MVE_v8f16, fp_to_uint>;
defm MVE_VCVTs32f32z : MVE_VCVT_fp_int_m<MVE_v4s32, MVE_v4f32, fp_to_sint>;
defm MVE_VCVTu32f32z : MVE_VCVT_fp_int_m<MVE_v4u32, MVE_v4f32, fp_to_uint>;
defm MVE_VCVTs16f16z : MVE_VCVT_fp_int_m<MVE_v8s16, MVE_v8f16, fp_to_sint, int_arm_mve_vcvt_int_fp>;
defm MVE_VCVTu16f16z : MVE_VCVT_fp_int_m<MVE_v8u16, MVE_v8f16, fp_to_uint, int_arm_mve_vcvt_int_fp>;
defm MVE_VCVTs32f32z : MVE_VCVT_fp_int_m<MVE_v4s32, MVE_v4f32, fp_to_sint, int_arm_mve_vcvt_int_fp>;
defm MVE_VCVTu32f32z : MVE_VCVT_fp_int_m<MVE_v4u32, MVE_v4f32, fp_to_uint, int_arm_mve_vcvt_int_fp>;
// Whereas VCVT for int->float rounds to nearest
defm MVE_VCVTf16s16n : MVE_VCVT_fp_int_m<MVE_v8f16, MVE_v8s16, sint_to_fp>;
defm MVE_VCVTf16u16n : MVE_VCVT_fp_int_m<MVE_v8f16, MVE_v8u16, uint_to_fp>;
defm MVE_VCVTf32s32n : MVE_VCVT_fp_int_m<MVE_v4f32, MVE_v4s32, sint_to_fp>;
defm MVE_VCVTf32u32n : MVE_VCVT_fp_int_m<MVE_v4f32, MVE_v4u32, uint_to_fp>;
defm MVE_VCVTf16s16n : MVE_VCVT_fp_int_m<MVE_v8f16, MVE_v8s16, sint_to_fp, int_arm_mve_vcvt_fp_int>;
defm MVE_VCVTf16u16n : MVE_VCVT_fp_int_m<MVE_v8f16, MVE_v8u16, uint_to_fp, int_arm_mve_vcvt_fp_int>;
defm MVE_VCVTf32s32n : MVE_VCVT_fp_int_m<MVE_v4f32, MVE_v4s32, sint_to_fp, int_arm_mve_vcvt_fp_int>;
defm MVE_VCVTf32u32n : MVE_VCVT_fp_int_m<MVE_v4f32, MVE_v4u32, uint_to_fp, int_arm_mve_vcvt_fp_int>;

let Predicates = [HasMVEFloat] in {
def : Pat<(v4i32 (fp_to_sint_sat v4f32:$src, i32)),
Expand Down
81 changes: 81 additions & 0 deletions llvm/test/CodeGen/Thumb2/mve-intrinsics/strict-intrinsics.ll
Original file line number Diff line number Diff line change
Expand Up @@ -329,4 +329,85 @@ entry:
ret <4 x float> %2
}


define arm_aapcs_vfpcc <8 x half> @test_vcvtq_f16_s16(<8 x i16> noundef %a) #0 {
; CHECK-LABEL: test_vcvtq_f16_s16:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vcvt.f16.s16 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = tail call <8 x half> @llvm.arm.mve.vcvt.fp.int.v8f16.v8i16(<8 x i16> %a, i32 0)
ret <8 x half> %0
}

define arm_aapcs_vfpcc <8 x half> @test_vcvtq_f16_u16(<8 x i16> noundef %a) #0 {
; CHECK-LABEL: test_vcvtq_f16_u16:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vcvt.f16.u16 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = tail call <8 x half> @llvm.arm.mve.vcvt.fp.int.v8f16.v8i16(<8 x i16> %a, i32 1)
ret <8 x half> %0
}

define arm_aapcs_vfpcc <4 x float> @test_vcvtq_f32_s32(<4 x i32> noundef %a) #0 {
; CHECK-LABEL: test_vcvtq_f32_s32:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vcvt.f32.s32 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = tail call <4 x float> @llvm.arm.mve.vcvt.fp.int.v4f32.v4i32(<4 x i32> %a, i32 0)
ret <4 x float> %0
}

define arm_aapcs_vfpcc <4 x float> @test_vcvtq_f32_u32(<4 x i32> noundef %a) #0 {
; CHECK-LABEL: test_vcvtq_f32_u32:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vcvt.f32.u32 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = tail call <4 x float> @llvm.arm.mve.vcvt.fp.int.v4f32.v4i32(<4 x i32> %a, i32 1)
ret <4 x float> %0
}

define arm_aapcs_vfpcc <8 x i16> @test_vcvtq_s16_f16(<8 x half> noundef %a) #0 {
; CHECK-LABEL: test_vcvtq_s16_f16:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vcvt.s16.f16 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = tail call <8 x i16> @llvm.arm.mve.vcvt.int.fp.v8i16.v8f16(<8 x half> %a, i32 0)
ret <8 x i16> %0
}

define arm_aapcs_vfpcc <4 x i32> @test_vcvtq_s32_f32(<4 x float> noundef %a) #0 {
; CHECK-LABEL: test_vcvtq_s32_f32:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vcvt.s32.f32 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = tail call <4 x i32> @llvm.arm.mve.vcvt.int.fp.v4i32.v4f32(<4 x float> %a, i32 0)
ret <4 x i32> %0
}

define arm_aapcs_vfpcc <8 x i16> @test_vcvtq_u16_f16(<8 x half> noundef %a) #0 {
; CHECK-LABEL: test_vcvtq_u16_f16:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vcvt.u16.f16 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = tail call <8 x i16> @llvm.arm.mve.vcvt.int.fp.v8i16.v8f16(<8 x half> %a, i32 1)
ret <8 x i16> %0
}

define arm_aapcs_vfpcc <4 x i32> @test_vcvtq_u32_f32(<4 x float> noundef %a) #0 {
; CHECK-LABEL: test_vcvtq_u32_f32:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: vcvt.u32.f32 q0, q0
; CHECK-NEXT: bx lr
entry:
%0 = tail call <4 x i32> @llvm.arm.mve.vcvt.int.fp.v4i32.v4f32(<4 x float> %a, i32 1)
ret <4 x i32> %0
}

attributes #0 = { strictfp }
Loading