r213444 - Use the dereferenceable attribute on C99 array parameters with static

Hal Finkel hfinkel at anl.gov
Fri Jul 18 18:41:07 PDT 2014


Author: hfinkel
Date: Fri Jul 18 20:41:07 2014
New Revision: 213444

URL: http://llvm.org/viewvc/llvm-project?rev=213444&view=rev
Log:
Use the dereferenceable attribute on C99 array parameters with static

In C99, an array parameter declarator might have the form:
  direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'

where the static keyword indicates that the caller will always provide a
pointer to the beginning of an array with at least the number of elements
specified by the assignment expression. For constant sizes, we can use the
new dereferenceable attribute to pass this information to the optimizer. For
VLAs, we don't know the size, but (for addrspace(0)) do know that the pointer
must be nonnull (and so we can use the nonnull attribute).

Modified:
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/test/CodeGen/vla.c

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=213444&r1=213443&r2=213444&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Fri Jul 18 20:41:07 2014
@@ -1486,13 +1486,49 @@ void CodeGenFunction::EmitFunctionProlog
         assert(AI != Fn->arg_end() && "Argument mismatch!");
         llvm::Value *V = AI;
 
-        if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg))
+        if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) {
           if ((NNAtt && NNAtt->isNonNull(PVD->getFunctionScopeIndex())) ||
               PVD->hasAttr<NonNullAttr>())
             AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
                                                 AI->getArgNo() + 1,
                                                 llvm::Attribute::NonNull));
 
+          QualType OTy = PVD->getOriginalType();
+          if (const auto *ArrTy =
+              getContext().getAsConstantArrayType(OTy)) {
+            // A C99 array parameter declaration with the static keyword also
+            // indicates dereferenceability, and if the size is constant we can
+            // use the dereferenceable attribute (which requires the size in
+            // bytes).
+            if (ArrTy->getSizeModifier() == VariableArrayType::Static) {
+              QualType ETy = ArrTy->getElementType();
+              uint64_t ArrSize = ArrTy->getSize().getZExtValue();
+              if (!ETy->isIncompleteType() && ETy->isConstantSizeType() &&
+                  ArrSize) {
+                llvm::AttrBuilder Attrs;
+                Attrs.addDereferenceableAttr(
+                  getContext().getTypeSizeInChars(ETy).getQuantity()*ArrSize);
+                AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
+                                                    AI->getArgNo() + 1, Attrs));
+              } else if (getContext().getTargetAddressSpace(ETy) == 0) {
+                AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
+                                                    AI->getArgNo() + 1,
+                                                    llvm::Attribute::NonNull));
+              }
+            }
+          } else if (const auto *ArrTy =
+                     getContext().getAsVariableArrayType(OTy)) {
+            // For C99 VLAs with the static keyword, we don't know the size so
+            // we can't use the dereferenceable attribute, but in addrspace(0)
+            // we know that it must be nonnull.
+            if (ArrTy->getSizeModifier() == VariableArrayType::Static &&
+                !getContext().getTargetAddressSpace(ArrTy->getElementType()))
+              AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
+                                                  AI->getArgNo() + 1,
+                                                  llvm::Attribute::NonNull));
+          }
+        }
+
         if (Arg->getType().isRestrictQualified())
           AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
                                               AI->getArgNo() + 1,

Modified: cfe/trunk/test/CodeGen/vla.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/vla.c?rev=213444&r1=213443&r2=213444&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/vla.c (original)
+++ cfe/trunk/test/CodeGen/vla.c Fri Jul 18 20:41:07 2014
@@ -195,3 +195,12 @@ void test7(int a[b(0)]) {
   // CHECK-LABEL: define void @test7(
   // CHECK: call i32 @b(i8* null)
 }
+
+// Make sure we emit dereferenceable or nonnull when the static keyword is
+// provided.
+void test8(int a[static 3]) { }
+// CHECK: define void @test8(i32* dereferenceable(12) %a)
+
+void test9(int n, int a[static n]) { }
+// CHECK: define void @test9(i32 %n, i32* nonnull %a)
+





More information about the cfe-commits mailing list