From 1ec33d54dfc07388c7bc7d637723ceeaa74869ee Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 28 Mar 2018 19:40:57 +0000 Subject: [PATCH] [Hexagon] Add support for "new" circular buffer intrinsics These instructions have been around for a long time, but we haven't supported intrinsics for them. The "new" vesrions use the CSx register for the start of the buffer instead of the K field in the Mx register. There is a related llvm patch. Patch by Brendon Cahoon. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@328725 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsHexagon.def | 23 ++++ lib/CodeGen/CGBuiltin.cpp | 94 ++++++++++++++ test/CodeGen/builtins-hexagon-circ.c | 156 ++++++++++++++++++++++++ 3 files changed, 273 insertions(+) create mode 100644 test/CodeGen/builtins-hexagon-circ.c diff --git a/include/clang/Basic/BuiltinsHexagon.def b/include/clang/Basic/BuiltinsHexagon.def index fda50b5358..c92a236c5c 100644 --- a/include/clang/Basic/BuiltinsHexagon.def +++ b/include/clang/Basic/BuiltinsHexagon.def @@ -39,6 +39,29 @@ BUILTIN(__builtin_circ_stw, "i*i*iiIi", "") BUILTIN(__builtin_circ_sth, "s*s*iiIi", "") BUILTIN(__builtin_circ_sthhi, "s*s*iiIi", "") BUILTIN(__builtin_circ_stb, "c*c*iiIi", "") +BUILTIN(__builtin_HEXAGON_L2_loadrub_pci, "iv*IiivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrb_pci, "iv*IiivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadruh_pci, "iv*IiivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrh_pci, "iv*IiivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadri_pci, "iv*IiivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrd_pci, "LLiv*IiivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrub_pcr, "iv*ivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrb_pcr, "iv*ivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadruh_pcr, "iv*ivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrh_pcr, "iv*ivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadri_pcr, "iv*ivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrd_pcr, "LLiv*ivC*", "") + +BUILTIN(__builtin_HEXAGON_S2_storerb_pci, "vv*IiiivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerh_pci, "vv*IiiivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerf_pci, "vv*IiiivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storeri_pci, "vv*IiiivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerd_pci, "vv*IiiLLivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerb_pcr, "vv*iivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerh_pcr, "vv*iivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerf_pcr, "vv*iivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storeri_pcr, "vv*iivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerd_pcr, "vv*iLLivC*", "") // The builtins above are not autogenerated from iset.py. // Make sure you do not overwrite these. diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 64146e2855..8458d4d8a2 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -10772,6 +10772,54 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, SmallVector Ops; Intrinsic::ID ID = Intrinsic::not_intrinsic; + auto MakeCircLd = [&](unsigned IntID, bool HasImm = true) { + // The base pointer is passed by address, so it needs to be loaded. + Address BP = EmitPointerWithAlignment(E->getArg(0)); + BP = Address(Builder.CreateBitCast(BP.getPointer(), Int8PtrPtrTy), + BP.getAlignment()); + llvm::Value *Base = Builder.CreateLoad(BP); + // Operands are Base, Increment, Modifier, Start. + if (HasImm) + Ops = { Base, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2)), + EmitScalarExpr(E->getArg(3)) }; + else + Ops = { Base, EmitScalarExpr(E->getArg(1)), + EmitScalarExpr(E->getArg(2)) }; + + llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(IntID), Ops); + llvm::Value *NewBase = Builder.CreateExtractValue(Result, 1); + llvm::Value *LV = Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), + NewBase->getType()->getPointerTo()); + Address Dest = EmitPointerWithAlignment(E->getArg(0)); + // The intrinsic generates two results. The new value for the base pointer + // needs to be stored. + Builder.CreateAlignedStore(NewBase, LV, Dest.getAlignment()); + return Builder.CreateExtractValue(Result, 0); + }; + + auto MakeCircSt = [&](unsigned IntID, bool HasImm = true) { + // The base pointer is passed by address, so it needs to be loaded. + Address BP = EmitPointerWithAlignment(E->getArg(0)); + BP = Address(Builder.CreateBitCast(BP.getPointer(), Int8PtrPtrTy), + BP.getAlignment()); + llvm::Value *Base = Builder.CreateLoad(BP); + // Operands are Base, Increment, Modifier, Value, Start. + if (HasImm) + Ops = { Base, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2)), + EmitScalarExpr(E->getArg(3)), EmitScalarExpr(E->getArg(4)) }; + else + Ops = { Base, EmitScalarExpr(E->getArg(1)), + EmitScalarExpr(E->getArg(2)), EmitScalarExpr(E->getArg(3)) }; + + llvm::Value *NewBase = Builder.CreateCall(CGM.getIntrinsic(IntID), Ops); + llvm::Value *LV = Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), + NewBase->getType()->getPointerTo()); + Address Dest = EmitPointerWithAlignment(E->getArg(0)); + // The intrinsic generates one result, which is the new value for the base + // pointer. It needs to be stored. + return Builder.CreateAlignedStore(NewBase, LV, Dest.getAlignment()); + }; + switch (BuiltinID) { case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry: case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B: { @@ -10817,6 +10865,52 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, Builder.CreateAlignedStore(Vprd, Base, Dest.getAlignment()); return Builder.CreateExtractValue(Result, 0); } + case Hexagon::BI__builtin_HEXAGON_L2_loadrub_pci: + return MakeCircLd(Intrinsic::hexagon_L2_loadrub_pci); + case Hexagon::BI__builtin_HEXAGON_L2_loadrb_pci: + return MakeCircLd(Intrinsic::hexagon_L2_loadrb_pci); + case Hexagon::BI__builtin_HEXAGON_L2_loadruh_pci: + return MakeCircLd(Intrinsic::hexagon_L2_loadruh_pci); + case Hexagon::BI__builtin_HEXAGON_L2_loadrh_pci: + return MakeCircLd(Intrinsic::hexagon_L2_loadrh_pci); + case Hexagon::BI__builtin_HEXAGON_L2_loadri_pci: + return MakeCircLd(Intrinsic::hexagon_L2_loadri_pci); + case Hexagon::BI__builtin_HEXAGON_L2_loadrd_pci: + return MakeCircLd(Intrinsic::hexagon_L2_loadrd_pci); + case Hexagon::BI__builtin_HEXAGON_L2_loadrub_pcr: + return MakeCircLd(Intrinsic::hexagon_L2_loadrub_pcr, /*HasImm=*/false); + case Hexagon::BI__builtin_HEXAGON_L2_loadrb_pcr: + return MakeCircLd(Intrinsic::hexagon_L2_loadrb_pcr, /*HasImm=*/false); + case Hexagon::BI__builtin_HEXAGON_L2_loadruh_pcr: + return MakeCircLd(Intrinsic::hexagon_L2_loadruh_pcr, /*HasImm=*/false); + case Hexagon::BI__builtin_HEXAGON_L2_loadrh_pcr: + return MakeCircLd(Intrinsic::hexagon_L2_loadrh_pcr, /*HasImm=*/false); + case Hexagon::BI__builtin_HEXAGON_L2_loadri_pcr: + return MakeCircLd(Intrinsic::hexagon_L2_loadri_pcr, /*HasImm=*/false); + case Hexagon::BI__builtin_HEXAGON_L2_loadrd_pcr: + return MakeCircLd(Intrinsic::hexagon_L2_loadrd_pcr, /*HasImm=*/false); + case Hexagon::BI__builtin_HEXAGON_S2_storerb_pci: + return MakeCircSt(Intrinsic::hexagon_S2_storerb_pci); + case Hexagon::BI__builtin_HEXAGON_S2_storerh_pci: + return MakeCircSt(Intrinsic::hexagon_S2_storerh_pci); + case Hexagon::BI__builtin_HEXAGON_S2_storerf_pci: + return MakeCircSt(Intrinsic::hexagon_S2_storerf_pci); + case Hexagon::BI__builtin_HEXAGON_S2_storeri_pci: + return MakeCircSt(Intrinsic::hexagon_S2_storeri_pci); + case Hexagon::BI__builtin_HEXAGON_S2_storerd_pci: + return MakeCircSt(Intrinsic::hexagon_S2_storerd_pci); + case Hexagon::BI__builtin_HEXAGON_S2_storerb_pcr: + return MakeCircSt(Intrinsic::hexagon_S2_storerb_pcr, /*HasImm=*/false); + case Hexagon::BI__builtin_HEXAGON_S2_storerh_pcr: + return MakeCircSt(Intrinsic::hexagon_S2_storerh_pcr, /*HasImm=*/false); + case Hexagon::BI__builtin_HEXAGON_S2_storerf_pcr: + return MakeCircSt(Intrinsic::hexagon_S2_storerf_pcr, /*HasImm=*/false); + case Hexagon::BI__builtin_HEXAGON_S2_storeri_pcr: + return MakeCircSt(Intrinsic::hexagon_S2_storeri_pcr, /*HasImm=*/false); + case Hexagon::BI__builtin_HEXAGON_S2_storerd_pcr: + return MakeCircSt(Intrinsic::hexagon_S2_storerd_pcr, /*HasImm=*/false); + default: + break; } // switch return nullptr; diff --git a/test/CodeGen/builtins-hexagon-circ.c b/test/CodeGen/builtins-hexagon-circ.c new file mode 100644 index 0000000000..dc8f5a693f --- /dev/null +++ b/test/CodeGen/builtins-hexagon-circ.c @@ -0,0 +1,156 @@ +// REQUIRES: hexagon-registered-target +// RUN: %clang_cc1 -triple hexagon-unknown-elf -emit-llvm %s -o - | FileCheck %s + +// CHECK-LABEL: test1 +// CHECK: @llvm.hexagon.L2.loadrub.pci +unsigned char test1(int mod, void *start) { + unsigned char *base = start; + return __builtin_HEXAGON_L2_loadrub_pci(&base, 4, mod, start); +} + +// CHECK-LABEL: test2 +// CHECK: @llvm.hexagon.L2.loadrb.pci +unsigned char test2(int mod, void *start) { + char *base = start; + return __builtin_HEXAGON_L2_loadrb_pci(&base, 4, mod, start); +} + +// CHECK-LABEL: test3 +// CHECK: @llvm.hexagon.L2.loadruh.pci +unsigned short test3(int mod, void *start) { + unsigned short *base = start; + return __builtin_HEXAGON_L2_loadruh_pci(&base, 4, mod, start); +} + +// CHECK-LABEL: test4 +// CHECK: @llvm.hexagon.L2.loadrh.pci +short test4(int mod, void *start) { + short *base = start; + return __builtin_HEXAGON_L2_loadrh_pci(&base, 4, mod, start); +} + +// CHECK-LABEL: test5 +// CHECK: @llvm.hexagon.L2.loadri.pci +int test5(int mod, void *start) { + int *base = start; + return __builtin_HEXAGON_L2_loadri_pci(&base, 4, mod, start); +} + +// CHECK-LABEL: test6 +// CHECK: @llvm.hexagon.L2.loadrd.pci +long long test6(int mod, void *start) { + long long *base = start; + return __builtin_HEXAGON_L2_loadrd_pci(&base, 8, mod, start); +} + +// CHECK-LABEL: test7 +// CHECK: @llvm.hexagon.L2.loadrub.pcr +unsigned char test7(int mod, void *start) { + unsigned char *base = start; + return __builtin_HEXAGON_L2_loadrub_pcr(&base, mod, start); +} + +// CHECK-LABEL: test8 +// CHECK: @llvm.hexagon.L2.loadrb.pcr +unsigned char test8(int mod, void *start) { + char *base = start; + return __builtin_HEXAGON_L2_loadrb_pcr(&base, mod, start); +} + +// CHECK-LABEL: test9 +// CHECK: @llvm.hexagon.L2.loadruh.pcr +unsigned short test9(int mod, void *start) { + unsigned short *base = start; + return __builtin_HEXAGON_L2_loadruh_pcr(&base, mod, start); +} + +// CHECK-LABEL: test10 +// CHECK: @llvm.hexagon.L2.loadrh.pcr +short test10(int mod, void *start) { + short *base = start; + return __builtin_HEXAGON_L2_loadrh_pcr(&base, mod, start); +} + +// CHECK-LABEL: test11 +// CHECK: @llvm.hexagon.L2.loadri.pcr +int test11(int mod, void *start) { + int *base = start; + return __builtin_HEXAGON_L2_loadri_pcr(&base, mod, start); +} + +// CHECK-LABEL: test12 +// CHECK: @llvm.hexagon.L2.loadrd.pcr +long long test12(int mod, void *start) { + long long *base = start; + return __builtin_HEXAGON_L2_loadrd_pcr(&base, mod, start); +} + +// CHECK-LABEL: test13 +// CHECK: @llvm.hexagon.S2.storerb.pci +void test13(int mod, void *start, char v) { + void *base = start; + __builtin_HEXAGON_S2_storerb_pci(&base, 4, mod, v, start); +} + +// CHECK-LABEL: test14 +// CHECK: @llvm.hexagon.S2.storerh.pci +void test14(int mod, void *start, short v) { + void *base = start; + __builtin_HEXAGON_S2_storerh_pci(&base, 4, mod, v, start); +} + +// CHECK-LABEL: test15 +// CHECK: @llvm.hexagon.S2.storerf.pci +void test15(int mod, void *start, short v) { + void *base = start; + __builtin_HEXAGON_S2_storerf_pci(&base, 4, mod, v, start); +} + +// CHECK-LABEL: test16 +// CHECK: @llvm.hexagon.S2.storeri.pci +void test16(int mod, void *start, int v) { + void *base = start; + __builtin_HEXAGON_S2_storeri_pci(&base, 4, mod, v, start); +} + +// CHECK-LABEL: test17 +// CHECK: @llvm.hexagon.S2.storerd.pci +void test17(int mod, void *start, long long v) { + void *base = start; + __builtin_HEXAGON_S2_storerd_pci(&base, 8, mod, v, start); +} + +// CHECK-LABEL: test18 +// CHECK: @llvm.hexagon.S2.storerb.pcr +void test18(int mod, void *start, char v) { + void *base = start; + __builtin_HEXAGON_S2_storerb_pcr(&base, mod, v, start); +} + +// CHECK-LABEL: test19 +// CHECK: @llvm.hexagon.S2.storerh.pcr +void test19(int mod, void *start, short v) { + void *base = start; + __builtin_HEXAGON_S2_storerh_pcr(&base, mod, v, start); +} + +// CHECK-LABEL: test20 +// CHECK: @llvm.hexagon.S2.storerf.pcr +void test20(int mod, void *start, short v) { + void *base = start; + __builtin_HEXAGON_S2_storerf_pcr(&base, mod, v, start); +} + +// CHECK-LABEL: test21 +// CHECK: @llvm.hexagon.S2.storeri.pcr +void test21(int mod, void *start, int v) { + void *base = start; + __builtin_HEXAGON_S2_storeri_pcr(&base, mod, v, start); +} + +// CHECK-LABEL: test22 +// CHECK: @llvm.hexagon.S2.storerd.pcr +void test22(int mod, void *start, long long v) { + void *base = start; + __builtin_HEXAGON_S2_storerd_pcr(&base, mod, v, start); +} -- 2.40.0