Hi Tim, Saleem, ARM supports instruction prefetch which the generic prefetch intrinsic is not able to describe. AArch64 has even more granular instructions.
This patchset adds __builtin_arm_prefetch intrinsic to ARM and AArch64. Note that they have different syntax, thus cannot be shared across platforms. Corresponding platform-independent ACLE intrinsics will be added in a separate patch. Cheers Yi
From bff083ba2403a8d881c9f97c83a0b22dd46e4ae5 Mon Sep 17 00:00:00 2001 From: Yi Kong <[email protected]> Date: Tue, 12 Aug 2014 09:27:39 +0100 Subject: [PATCH 1/2] ARM: Prefetch intrinsics --- include/clang/Basic/BuiltinsARM.def | 3 +++ lib/CodeGen/CGBuiltin.cpp | 12 ++++++++++++ lib/Sema/SemaChecking.cpp | 5 +++++ test/CodeGen/builtins-arm.c | 11 +++++++++++ test/Sema/builtins-arm.c | 5 +++++ 5 files changed, 36 insertions(+) diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def index 2e5eac6..4c1400a 100644 --- a/include/clang/Basic/BuiltinsARM.def +++ b/include/clang/Basic/BuiltinsARM.def @@ -80,6 +80,9 @@ BUILTIN(__builtin_arm_dmb, "vUi", "nc") BUILTIN(__builtin_arm_dsb, "vUi", "nc") BUILTIN(__builtin_arm_isb, "vUi", "nc") +// Prefetch +BUILTIN(__builtin_arm_prefetch, "vvC*UiUi", "nc") + // MSVC LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES) LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 79f6925..092c44f 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -3088,6 +3088,18 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, return Builder.CreateCall(F, llvm::ConstantInt::get(Int32Ty, HintID)); } + if (BuiltinID == ARM::BI__builtin_arm_prefetch) { + Value *Address = EmitScalarExpr(E->getArg(0)); + Value *RW = EmitScalarExpr(E->getArg(1)); + Value *IsData = EmitScalarExpr(E->getArg(2)); + + // Locality is not supported on ARM target + Value *Locality = llvm::ConstantInt::get(Int32Ty, 3); + + Value *F = CGM.getIntrinsic(Intrinsic::prefetch); + return Builder.CreateCall4(F, Address, RW, Locality, IsData); + } + if (BuiltinID == ARM::BI__builtin_arm_rbit) { return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_rbit), EmitScalarExpr(E->getArg(0)), diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 7bc3ba7..abda2d2 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -624,6 +624,11 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 64); } + if (BuiltinID == ARM::BI__builtin_arm_prefetch) { + return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1) || + SemaBuiltinConstantArgRange(TheCall, 2, 0, 1); + } + if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall)) return true; diff --git a/test/CodeGen/builtins-arm.c b/test/CodeGen/builtins-arm.c index a51df15..686ae4e 100644 --- a/test/CodeGen/builtins-arm.c +++ b/test/CodeGen/builtins-arm.c @@ -66,3 +66,14 @@ void test_barrier() { unsigned rbit(unsigned a) { return __builtin_arm_rbit(a); } + +void prefetch(int i) { + __builtin_arm_prefetch(&i, 0, 1); +// CHECK: call {{.*}} @llvm.prefetch(i8* %0, i32 0, i32 3, i32 1) + + __builtin_arm_prefetch(&i, 1, 1); +// CHECK: call {{.*}} @llvm.prefetch(i8* %0, i32 1, i32 3, i32 1) + + __builtin_arm_prefetch(&i, 1, 0); +// CHECK: call {{.*}} @llvm.prefetch(i8* %0, i32 1, i32 3, i32 0) +} diff --git a/test/Sema/builtins-arm.c b/test/Sema/builtins-arm.c index 6c367d3..cc4af7d 100644 --- a/test/Sema/builtins-arm.c +++ b/test/Sema/builtins-arm.c @@ -37,4 +37,9 @@ void test3() { __builtin_arm_isb(18); // expected-error {{argument should be a value from 0 to 15}} } +void test4() { + __builtin_arm_prefetch(0, 2, 0); // expected-error {{argument should be a value from 0 to 1}} + __builtin_arm_prefetch(0, 0, 2); // expected-error {{argument should be a value from 0 to 1}} +} + #endif -- 2.0.4
From c7e356d91499e11899ea3b109f10e57f01ee4e4b Mon Sep 17 00:00:00 2001 From: Yi Kong <[email protected]> Date: Tue, 12 Aug 2014 09:28:17 +0100 Subject: [PATCH 2/2] AArch64: Prefetch intrinsic --- include/clang/Basic/BuiltinsAArch64.def | 3 +++ lib/CodeGen/CGBuiltin.cpp | 23 +++++++++++++++++++++++ lib/Sema/SemaChecking.cpp | 7 +++++++ test/CodeGen/builtins-arm64.c | 14 ++++++++++++++ test/Sema/builtins-arm64.c | 7 +++++++ 5 files changed, 54 insertions(+) diff --git a/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def index 695ecf9..9d223c3 100644 --- a/include/clang/Basic/BuiltinsAArch64.def +++ b/include/clang/Basic/BuiltinsAArch64.def @@ -50,4 +50,7 @@ BUILTIN(__builtin_arm_dmb, "vUi", "nc") BUILTIN(__builtin_arm_dsb, "vUi", "nc") BUILTIN(__builtin_arm_isb, "vUi", "nc") +// Prefetch +BUILTIN(__builtin_arm_prefetch, "vvC*UiUiUiUi", "nc") + #undef BUILTIN diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 092c44f..99f4b21 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -3854,6 +3854,29 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, return Builder.CreateCall(F, llvm::ConstantInt::get(Int32Ty, HintID)); } + if (BuiltinID == AArch64::BI__builtin_arm_prefetch) { + Value *Address = EmitScalarExpr(E->getArg(0)); + Value *RW = EmitScalarExpr(E->getArg(1)); + Value *CacheLevel = EmitScalarExpr(E->getArg(2)); + Value *RetentionPolicy = EmitScalarExpr(E->getArg(3)); + Value *IsData = EmitScalarExpr(E->getArg(4)); + + Value *Locality = nullptr; + if (cast<llvm::ConstantInt>(RetentionPolicy)->isZero()) { + // Temporal fetch, needs to convert cache level to locality. + Locality = llvm::ConstantInt::get(Int32Ty, + -cast<llvm::ConstantInt>(CacheLevel)->getValue() + 3); + } else { + // Streaming fetch. + Locality = llvm::ConstantInt::get(Int32Ty, 0); + } + + // FIXME: We need AArch64 specific LLVM intrinsic if we want to specify + // PLDL3STRM or PLDL2STRM. + Value *F = CGM.getIntrinsic(Intrinsic::prefetch); + return Builder.CreateCall4(F, Address, RW, Locality, IsData); + } + if (BuiltinID == AArch64::BI__builtin_arm_rbit) { assert((getContext().getTypeSize(E->getType()) == 32) && "rbit of unusual size!"); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index abda2d2..95411f5 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -661,6 +661,13 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 128); } + if (BuiltinID == AArch64::BI__builtin_arm_prefetch) { + return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1) || + SemaBuiltinConstantArgRange(TheCall, 2, 0, 2) || + SemaBuiltinConstantArgRange(TheCall, 3, 0, 1) || + SemaBuiltinConstantArgRange(TheCall, 4, 0, 1); + } + if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall)) return true; diff --git a/test/CodeGen/builtins-arm64.c b/test/CodeGen/builtins-arm64.c index cfa1181..cc1f547 100644 --- a/test/CodeGen/builtins-arm64.c +++ b/test/CodeGen/builtins-arm64.c @@ -29,3 +29,17 @@ void barriers() { __builtin_arm_dsb(2); //CHECK: call {{.*}} @llvm.aarch64.dsb(i32 2) __builtin_arm_isb(3); //CHECK: call {{.*}} @llvm.aarch64.isb(i32 3) } + +void prefetch() { + __builtin_arm_prefetch(0, 1, 2, 0, 1); // pstl3keep +// CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 1, i32 1, i32 1) + + __builtin_arm_prefetch(0, 0, 0, 1, 1); // pldl1keep +// CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 0, i32 0, i32 1) + + __builtin_arm_prefetch(0, 0, 0, 1, 1); // pldl1strm +// CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 0, i32 0, i32 1) + + __builtin_arm_prefetch(0, 0, 0, 0, 0); // plil1keep +// CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 0, i32 3, i32 0) +} diff --git a/test/Sema/builtins-arm64.c b/test/Sema/builtins-arm64.c index 113f4fc..2779984 100644 --- a/test/Sema/builtins-arm64.c +++ b/test/Sema/builtins-arm64.c @@ -22,3 +22,10 @@ void test_memory_barriers() { __builtin_arm_dsb(17); // expected-error {{argument should be a value from 0 to 15}} __builtin_arm_isb(18); // expected-error {{argument should be a value from 0 to 15}} } + +void test_prefetch() { + __builtin_arm_prefetch(0, 2, 0, 0, 0); // expected-error {{argument should be a value from 0 to 1}} + __builtin_arm_prefetch(0, 0, 3, 0, 0); // expected-error {{argument should be a value from 0 to 2}} + __builtin_arm_prefetch(0, 0, 0, 2, 0); // expected-error {{argument should be a value from 0 to 1}} + __builtin_arm_prefetch(0, 0, 0, 0, 2); // expected-error {{argument should be a value from 0 to 1}} +} -- 2.0.4
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
