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

Reply via email to