[cfe-commits] [PATCH] Assume Aligned - Clang

hfinkel at anl.gov hfinkel at anl.gov
Mon Dec 3 08:43:20 PST 2012


hfinkel added you to the CC list for the revision "Assume Aligned - Clang".

Clang patch for __builtin_assume_aligned

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

Files:
  include/clang/Basic/Builtins.def
  include/clang/Sema/Sema.h
  lib/AST/ExprConstant.cpp
  lib/CodeGen/CGBuiltin.cpp
  lib/Sema/SemaChecking.cpp
  test/CodeGen/builtin-assume-aligned.c
  test/Sema/builtin-assume-aligned.c

Index: include/clang/Basic/Builtins.def
===================================================================
--- include/clang/Basic/Builtins.def
+++ include/clang/Basic/Builtins.def
@@ -402,6 +402,7 @@
 BUILTIN(__builtin_va_end, "vA", "n")
 BUILTIN(__builtin_va_copy, "vAA", "n")
 BUILTIN(__builtin_stdarg_start, "vA.", "n")
+BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nc")
 BUILTIN(__builtin_bcmp, "iv*v*z", "n")
 BUILTIN(__builtin_bcopy, "vv*v*z", "n")
 BUILTIN(__builtin_bzero, "vv*z", "nF")
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -7189,6 +7189,7 @@
 
 private:
   bool SemaBuiltinPrefetch(CallExpr *TheCall);
+  bool SemaBuiltinAssumeAligned(CallExpr *TheCall);
   bool SemaBuiltinObjectSize(CallExpr *TheCall);
   bool SemaBuiltinLongjmp(CallExpr *TheCall);
   ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult);
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -4313,6 +4313,7 @@
   }
 
   case Builtin::BI__builtin_expect:
+  case Builtin::BI__builtin_assume_aligned:
     return Visit(E->getArg(0));
 
   case Builtin::BIstrlen:
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -354,6 +354,26 @@
                                         "expval");
     return RValue::get(Result);
   }
+  case Builtin::BI__builtin_assume_aligned: {
+    Value *ArgValue = EmitScalarExpr(E->getArg(0));
+
+    Value *AlignmentValue = EmitScalarExpr(E->getArg(1));
+    AlignmentValue = Builder.CreateIntCast(AlignmentValue, Int32Ty, false);
+
+    Value *OffsetValue = (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) :
+      llvm::ConstantInt::get(Int32Ty, 0);
+
+    llvm::SmallVector<llvm::Type *, 2> Types;
+    Types.push_back(ArgValue->getType());
+    Types.push_back(OffsetValue->getType());
+
+    Value *FnAssumeAligned =
+      CGM.getIntrinsic(Intrinsic::assume_aligned, Types);
+
+    Value *Result = Builder.CreateCall3(FnAssumeAligned, ArgValue,
+      AlignmentValue, OffsetValue, "alignedval");
+    return RValue::get(Result);
+  }
   case Builtin::BI__builtin_bswap16:
   case Builtin::BI__builtin_bswap32:
   case Builtin::BI__builtin_bswap64: {
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -159,6 +159,10 @@
     if (SemaBuiltinPrefetch(TheCall))
       return ExprError();
     break;
+  case Builtin::BI__builtin_assume_aligned:
+    if (SemaBuiltinAssumeAligned(TheCall))
+      return ExprError();
+    break;
   case Builtin::BI__builtin_object_size:
     if (SemaBuiltinObjectSize(TheCall))
       return ExprError();
@@ -1582,6 +1586,52 @@
   return false;
 }
 
+/// Handle __builtin_assume_aligned.
+// This is declared to take (const void*, size_t, ...) and can take one
+// optional constant int args.
+bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) {
+  unsigned NumArgs = TheCall->getNumArgs();
+
+  if (NumArgs > 3)
+    return Diag(TheCall->getLocEnd(),
+             diag::err_typecheck_call_too_many_args_at_most)
+             << 0 /*function call*/ << 3 << NumArgs
+             << TheCall->getSourceRange();
+
+  // Argument 0 is checked for us; the alignment must be a constant integer.
+  Expr *Arg = TheCall->getArg(1);
+
+  // We can't check the value of a dependent argument.
+  if (!Arg->isTypeDependent() && !Arg->isValueDependent()) {
+    llvm::APSInt Result;
+    if (SemaBuiltinConstantArg(TheCall, 1, Result))
+      return true;
+
+    if (!Result.isIntN(32) || !Result.isUnsigned())
+      return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+           << "0" << "2147483648" << Arg->getSourceRange();
+    if (!Result.isPowerOf2())
+      return Diag(TheCall->getLocStart(),
+                  diag::err_attribute_aligned_not_power_of_two)
+           << Arg->getSourceRange();
+  }
+
+  if (NumArgs > 2) {
+    Arg = TheCall->getArg(2);
+    QualType T = Arg->getType();
+
+    // Note: gcc specifies the prototype as taking a size_t, but LLVM can
+    // handle only 32-bit alignment values.
+    if (!T->isIntegralType(Context))
+      return Diag(TheCall->getLocStart(),
+               diag::err_typecheck_converted_constant_expression)
+          << T << "an integral type" << Arg->getSourceRange();
+  }
+
+  return false;
+}
+
+
 /// SemaBuiltinConstantArg - Handle a check if argument ArgNum of CallExpr
 /// TheCall is a constant expression.
 bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
Index: test/CodeGen/builtin-assume-aligned.c
===================================================================
--- /dev/null
+++ test/CodeGen/builtin-assume-aligned.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: @test1
+int test1(int *a) {
+// CHECK: @llvm.assume.aligned.p0i8.i64
+  a = __builtin_assume_aligned(a, 32, 0ull);
+  return a[0];
+}
+
+// CHECK: @test2
+int test2(int *a) {
+// CHECK: @llvm.assume.aligned.p0i8.i32
+  a = __builtin_assume_aligned(a, 32, 0);
+  return a[0];
+}
+
+// CHECK: @test3
+int test3(int *a) {
+// CHECK: @llvm.assume.aligned.p0i8.i32
+  a = __builtin_assume_aligned(a, 32);
+  return a[0];
+}
+
Index: test/Sema/builtin-assume-aligned.c
===================================================================
--- /dev/null
+++ test/Sema/builtin-assume-aligned.c
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int test1(int *a) {
+  a = __builtin_assume_aligned(a, 32, 0ull);
+  return a[0];
+}
+
+int test2(int *a) {
+  a = __builtin_assume_aligned(a, 32, 0);
+  return a[0];
+}
+
+int test3(int *a) {
+  a = __builtin_assume_aligned(a, 32);
+  return a[0];
+}
+
+int test4(int *a) {
+  a = __builtin_assume_aligned(a, -32); // expected-error {{argument should be a value from}}
+  return a[0];
+}
+
+int test5(int *a, unsigned *b) {
+  a = __builtin_assume_aligned(a, 32, b); // expected-error {{is not implicitly convertible to an integral type}}
+  return a[0];
+}
+
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D149.1.patch
Type: text/x-patch
Size: 6278 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20121203/c791c379/attachment.bin>


More information about the cfe-commits mailing list