[PATCH] [RFC] __builtin___clear_cache support in LLVM

Renato Golin renato.golin at linaro.org
Fri Mar 14 11:24:59 PDT 2014


Hi jfb, dsanders, rafael,

This is only the LLVM part of implementing __builtin___clear_cache. It consists in:

1. Adding the @llvm.clear_cache builtin
2. Mapping it to nothing by default
3. Mapping it to __clear_cache library call on ARM and MIPS

There are some uncertainties:

1. Is the name @llvm.clear_cache good enough? Is this the right way to implement a builtin?
2. Making it a call in TLI seems cheap (as in bad), maybe there's a better way of doing that target-specific

If this is good enough, and after thorough review, I'll also add it to the LangRef on the same commit.

http://llvm-reviews.chandlerc.com/D3084

Files:
  include/llvm/IR/Intrinsics.td
  include/llvm/Target/TargetLowering.h
  lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  lib/Target/ARM/ARMISelLowering.h
  lib/Target/Mips/MipsISelLowering.h
  test/CodeGen/ARM/cache-intrinsic.ll
  test/CodeGen/Mips/cache-intrinsic.ll
  test/CodeGen/X86/cache-intrinsic.ll

Index: include/llvm/IR/Intrinsics.td
===================================================================
--- include/llvm/IR/Intrinsics.td
+++ include/llvm/IR/Intrinsics.td
@@ -509,6 +509,11 @@
 def int_convertuu  : Intrinsic<[llvm_anyint_ty],
                                [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>;
 
+// Clear cache intrinsic, default to ignore (ie. emit nothing)
+// maps to void __clear_cache() on supporting platforms
+def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty],
+                                [IntrReadWriteArgMem], "llvm.clear_cache">;
+
 //===----------------------------------------------------------------------===//
 // Target-specific intrinsics
 //===----------------------------------------------------------------------===//
Index: include/llvm/Target/TargetLowering.h
===================================================================
--- include/llvm/Target/TargetLowering.h
+++ include/llvm/Target/TargetLowering.h
@@ -2108,6 +2108,11 @@
     return false;
   }
 
+  /// Return the builtin name for the __builtin___clear_cache intrinsic
+  virtual const char * getClearCacheBuiltinName() const {
+    return 0;
+  }
+
   /// Return the type that should be used to zero or sign extend a
   /// zeroext/signext integer argument or return value.  FIXME: Most C calling
   /// convention requires the return type to be promoted, but this is not true
Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -5396,6 +5396,8 @@
     (void)getControlRoot();
     return 0;
   }
+  case Intrinsic::clear_cache:
+    return TLI->getClearCacheBuiltinName();
   case Intrinsic::donothing:
     // ignore
     return 0;
Index: lib/Target/ARM/ARMISelLowering.h
===================================================================
--- lib/Target/ARM/ARMISelLowering.h
+++ lib/Target/ARM/ARMISelLowering.h
@@ -386,6 +386,11 @@
     bool shouldConvertConstantLoadToIntImm(const APInt &Imm,
                                            Type *Ty) const override;
 
+    /// Clear cache library call
+    const char * getClearCacheBuiltinName() const {
+      return "__clear_cache";
+    }
+
   protected:
     std::pair<const TargetRegisterClass*, uint8_t>
     findRepresentativeClass(MVT VT) const override;
Index: lib/Target/Mips/MipsISelLowering.h
===================================================================
--- lib/Target/Mips/MipsISelLowering.h
+++ lib/Target/Mips/MipsISelLowering.h
@@ -580,6 +580,11 @@
                                     bool MemcpyStrSrc,
                                     MachineFunction &MF) const;
 
+    /// Clear cache library call
+    const char * getClearCacheBuiltinName() const {
+      return "__clear_cache";
+    }
+
     /// isFPImmLegal - Returns true if the target can instruction select the
     /// specified FP immediate natively. If false, the legalizer will
     /// materialize the FP immediate as a load from a constant pool.
Index: test/CodeGen/ARM/cache-intrinsic.ll
===================================================================
--- /dev/null
+++ test/CodeGen/ARM/cache-intrinsic.ll
@@ -0,0 +1,26 @@
+; RUN: llc %s -o - | FileCheck %s
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7--linux-gnueabihf"
+
+ at buffer = global [32 x i8] c"This is a largely unused buffer\00", align 1
+ at .str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+ at .str1 = private unnamed_addr constant [25 x i8] c"Still, largely unused...\00", align 1
+
+define i32 @main() {
+entry:
+  %retval = alloca i32, align 4
+  store i32 0, i32* %retval
+  %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0))
+  %call1 = call i8* @strcpy(i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0), i8* getelementptr inbounds ([25 x i8]* @.str1, i32 0, i32 0)) #3
+  call void @llvm.clear_cache(i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0), i8* getelementptr inbounds (i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0), i32 32)) #3
+  %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0))
+  ret i32 0
+}
+
+; CHECK: __clear_cache
+
+declare i32 @printf(i8*, ...)
+
+declare i8* @strcpy(i8*, i8*)
+
+declare void @llvm.clear_cache(i8*, i8*)
Index: test/CodeGen/Mips/cache-intrinsic.ll
===================================================================
--- /dev/null
+++ test/CodeGen/Mips/cache-intrinsic.ll
@@ -0,0 +1,26 @@
+; RUN: llc %s -o - | FileCheck %s
+target datalayout = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64"
+target triple = "mips--linux-gnu"
+
+ at buffer = global [32 x i8] c"This is a largely unused buffer\00", align 1
+ at .str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+ at .str1 = private unnamed_addr constant [25 x i8] c"Still, largely unused...\00", align 1
+
+define i32 @main() {
+entry:
+  %retval = alloca i32, align 4
+  store i32 0, i32* %retval
+  %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0))
+  %call1 = call i8* @strcpy(i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0), i8* getelementptr inbounds ([25 x i8]* @.str1, i32 0, i32 0)) #3
+  call void @llvm.clear_cache(i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0), i8* getelementptr inbounds (i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0), i32 32)) #3
+  %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0))
+  ret i32 0
+}
+
+; CHECK: __clear_cache
+
+declare i32 @printf(i8*, ...)
+
+declare i8* @strcpy(i8*, i8*)
+
+declare void @llvm.clear_cache(i8*, i8*)
Index: test/CodeGen/X86/cache-intrinsic.ll
===================================================================
--- /dev/null
+++ test/CodeGen/X86/cache-intrinsic.ll
@@ -0,0 +1,26 @@
+; RUN: llc %s -o - | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at buffer = global [32 x i8] c"This is a largely unused buffer\00", align 16
+ at .str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+ at .str1 = private unnamed_addr constant [25 x i8] c"Still, largely unused...\00", align 1
+
+define i32 @main() {
+entry:
+  %retval = alloca i32, align 4
+  store i32 0, i32* %retval
+  %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0))
+  %call1 = call i8* @strcpy(i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0), i8* getelementptr inbounds ([25 x i8]* @.str1, i32 0, i32 0)) #3
+  call void @llvm.clear_cache(i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0), i8* getelementptr inbounds (i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0), i32 32)) #3
+  %call3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([32 x i8]* @buffer, i32 0, i32 0))
+  ret i32 0
+}
+
+; CHECK-NOT: __clear_cache
+
+declare i32 @printf(i8*, ...)
+
+declare i8* @strcpy(i8*, i8*)
+
+declare void @llvm.clear_cache(i8*, i8*)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3084.1.patch
Type: text/x-patch
Size: 7619 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140314/d37b8ec5/attachment.bin>


More information about the llvm-commits mailing list