[llvm-commits] [poolalloc] r168332 - in /poolalloc/trunk: lib/DSA/Local.cpp test/dsa/regression/2012-11-19.MultipleVAStartAlias.ll

Will Dietz wdietz2 at illinois.edu
Mon Nov 19 13:44:43 PST 2012


Author: wdietz2
Date: Mon Nov 19 15:44:43 2012
New Revision: 168332

URL: http://llvm.org/viewvc/llvm-project?rev=168332&view=rev
Log:
Improve handling of multiple va.start invocations.

Use the same DSNode to represent the argument array, so different
va_start invocations will have aliasing pointers.

Note that I don't bother putting the VAArray Node into the DSGraph,
as presently there's no reason for the DSGraph itself or its users
to need to query for this node AFAIK.

Resolves PR14147, and testcase taken from that bug report.

Thanks Jingyue!

Added:
    poolalloc/trunk/test/dsa/regression/2012-11-19.MultipleVAStartAlias.ll
Modified:
    poolalloc/trunk/lib/DSA/Local.cpp

Modified: poolalloc/trunk/lib/DSA/Local.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/Local.cpp?rev=168332&r1=168331&r2=168332&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/Local.cpp (original)
+++ poolalloc/trunk/lib/DSA/Local.cpp Mon Nov 19 15:44:43 2012
@@ -75,6 +75,7 @@
     Function* FB;
     LocalDataStructures* DS;
     const DataLayout& TD;
+    DSNode *VAArray;
 
     ////////////////////////////////////////////////////////////////////////////
     // Helper functions used to implement the visitation functions...
@@ -143,7 +144,7 @@
 
   public:
     GraphBuilder(Function &f, DSGraph &g, LocalDataStructures& DSi)
-      : G(g), FB(&f), DS(&DSi), TD(g.getDataLayout()) {
+      : G(g), FB(&f), DS(&DSi), TD(g.getDataLayout()), VAArray(0) {
       // Create scalar nodes for all pointer arguments...
       for (Function::arg_iterator I = f.arg_begin(), E = f.arg_end();
            I != E; ++I) {
@@ -205,7 +206,7 @@
 
     // GraphBuilder ctor for working on the globals graph
     explicit GraphBuilder(DSGraph& g)
-      :G(g), FB(0), TD(g.getDataLayout())
+      :G(g), FB(0), TD(g.getDataLayout()), VAArray(0)
     {}
 
     void mergeInGlobalInitializer(GlobalVariable *GV);
@@ -852,7 +853,7 @@
   // And assosiate the right node with the VANode for this function
   // so it can be merged with the right arguments from callsites
 
-  DSNodeHandle RetNH = getValueDest(*CS.arg_begin());
+  DSNodeHandle RetNH = getValueDest(CS.getArgument(0));
 
   if (DSNode *N = RetNH.getNode())
     visitVAStartNode(N);
@@ -872,7 +873,9 @@
   if (VANH.isNull()) VANH.mergeWith(createNode());
 
   // Create a dsnode for an array of pointers to the VAInfo for this func
-  DSNode * VAArray = createNode();
+  // We create one such array for each function analyzed, as all
+  // calls to va_start will populate their argument with the same data.
+  if (!VAArray) VAArray = createNode();
   VAArray->setArrayMarker();
   VAArray->foldNodeCompletely();
   VAArray->setLink(0,VANH);
@@ -900,6 +903,7 @@
       N->growSize(24); //sizeof the va_list struct mentioned above
     N->setLink(8,VAArray); //first i8*
     N->setLink(16,VAArray); //second i8*
+
     break;
   default:
     // FIXME: For now we abort if we don't know how to handle this arch
@@ -971,19 +975,21 @@
       ->foldNodeCompletely();
     return true;
   case Intrinsic::vaend:
+    // TODO: What to do here?
+    return true;
   case Intrinsic::memcpy: 
   case Intrinsic::memmove: {
     // Merge the first & second arguments, and mark the memory read and
     // modified.
-    DSNodeHandle RetNH = getValueDest(*CS.arg_begin());
-    RetNH.mergeWith(getValueDest(*(CS.arg_begin()+1)));
+    DSNodeHandle RetNH = getValueDest(CS.getArgument(0));
+    RetNH.mergeWith(getValueDest(CS.getArgument(1)));
     if (DSNode *N = RetNH.getNode())
       N->setModifiedMarker()->setReadMarker();
     return true;
   }
   case Intrinsic::memset:
     // Mark the memory modified.
-    if (DSNode *N = getValueDest(*CS.arg_begin()).getNode())
+    if (DSNode *N = getValueDest(CS.getArgument(0)).getNode())
       N->setModifiedMarker();
     return true;
 
@@ -1013,7 +1019,7 @@
 #endif
 
   case Intrinsic::eh_typeid_for: {
-    DSNodeHandle Ptr = getValueDest(*CS.arg_begin());
+    DSNodeHandle Ptr = getValueDest(CS.getArgument(0));
     Ptr.getNode()->setReadMarker();
     Ptr.getNode()->setIncompleteMarker();
     return true;
@@ -1125,7 +1131,7 @@
            "Too many arguments/incorrect function signature!");
 
   std::vector<DSNodeHandle> Args;
-  Args.reserve(CS.arg_end()-CS.arg_begin());
+  Args.reserve(CS.arg_size());
   DSNodeHandle VarArgNH;
 
   // Calculate the arguments vector...

Added: poolalloc/trunk/test/dsa/regression/2012-11-19.MultipleVAStartAlias.ll
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/test/dsa/regression/2012-11-19.MultipleVAStartAlias.ll?rev=168332&view=auto
==============================================================================
--- poolalloc/trunk/test/dsa/regression/2012-11-19.MultipleVAStartAlias.ll (added)
+++ poolalloc/trunk/test/dsa/regression/2012-11-19.MultipleVAStartAlias.ll Mon Nov 19 15:44:43 2012
@@ -0,0 +1,122 @@
+; PR14147
+; RUN: dsaopt %s -dsa-local -analyze -check-same-node=@sum:reg_save_area, at sum:reg_save_area16
+; ModuleID = 'test-vaarg.bc'
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.__va_list_tag = type { i32, i32, i8*, i8* }
+
+ at .str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
+
+define i32 @sum(i32 %n, ...) nounwind uwtable {
+entry:
+  %vl = alloca [1 x %struct.__va_list_tag], align 16
+  %arraydecay1 = bitcast [1 x %struct.__va_list_tag]* %vl to i8*
+  call void @llvm.va_start(i8* %arraydecay1)
+  %cmp32 = icmp sgt i32 %n, 0
+  br i1 %cmp32, label %for.body.lr.ph, label %for.end.thread
+
+for.end.thread:                                   ; preds = %entry
+  call void @llvm.va_end(i8* %arraydecay1)
+  call void @llvm.va_start(i8* %arraydecay1)
+  br label %for.end26
+
+for.body.lr.ph:                                   ; preds = %entry
+  %gp_offset_p = getelementptr inbounds [1 x %struct.__va_list_tag]* %vl, i64 0, i64 0, i32 0
+  %0 = getelementptr inbounds [1 x %struct.__va_list_tag]* %vl, i64 0, i64 0, i32 3
+  %overflow_arg_area_p = getelementptr inbounds [1 x %struct.__va_list_tag]* %vl, i64 0, i64 0, i32 2
+  %gp_offset.pre = load i32* %gp_offset_p, align 16
+  br label %for.body
+
+for.body:                                         ; preds = %vaarg.end, %for.body.lr.ph
+  %gp_offset = phi i32 [ %gp_offset.pre, %for.body.lr.ph ], [ %gp_offset39, %vaarg.end ]
+  %result.034 = phi i32 [ 0, %for.body.lr.ph ], [ %add, %vaarg.end ]
+  %i.033 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %vaarg.end ]
+  %fits_in_gp = icmp ult i32 %gp_offset, 41
+  br i1 %fits_in_gp, label %vaarg.in_reg, label %vaarg.in_mem
+
+vaarg.in_reg:                                     ; preds = %for.body
+  %reg_save_area = load i8** %0, align 16
+  %1 = sext i32 %gp_offset to i64
+  %2 = getelementptr i8* %reg_save_area, i64 %1
+  %3 = add i32 %gp_offset, 8
+  store i32 %3, i32* %gp_offset_p, align 16
+  br label %vaarg.end
+
+vaarg.in_mem:                                     ; preds = %for.body
+  %overflow_arg_area = load i8** %overflow_arg_area_p, align 8
+  %overflow_arg_area.next = getelementptr i8* %overflow_arg_area, i64 8
+  store i8* %overflow_arg_area.next, i8** %overflow_arg_area_p, align 8
+  br label %vaarg.end
+
+vaarg.end:                                        ; preds = %vaarg.in_mem, %vaarg.in_reg
+  %gp_offset39 = phi i32 [ %3, %vaarg.in_reg ], [ %gp_offset, %vaarg.in_mem ]
+  %vaarg.addr.in = phi i8* [ %2, %vaarg.in_reg ], [ %overflow_arg_area, %vaarg.in_mem ]
+  %vaarg.addr = bitcast i8* %vaarg.addr.in to i32*
+  %4 = load i32* %vaarg.addr, align 4
+  %add = add nsw i32 %4, %result.034
+  %inc = add nsw i32 %i.033, 1
+  %exitcond36 = icmp eq i32 %inc, %n
+  br i1 %exitcond36, label %for.end, label %for.body
+
+for.end:                                          ; preds = %vaarg.end
+  call void @llvm.va_end(i8* %arraydecay1)
+  call void @llvm.va_start(i8* %arraydecay1)
+  br i1 %cmp32, label %for.body9.lr.ph, label %for.end26
+
+for.body9.lr.ph:                                  ; preds = %for.end
+  %gp_offset_p12 = getelementptr inbounds [1 x %struct.__va_list_tag]* %vl, i64 0, i64 0, i32 0
+  %5 = getelementptr inbounds [1 x %struct.__va_list_tag]* %vl, i64 0, i64 0, i32 3
+  %overflow_arg_area_p18 = getelementptr inbounds [1 x %struct.__va_list_tag]* %vl, i64 0, i64 0, i32 2
+  %gp_offset13.pre = load i32* %gp_offset_p12, align 16
+  br label %for.body9
+
+for.body9:                                        ; preds = %vaarg.end21, %for.body9.lr.ph
+  %gp_offset13 = phi i32 [ %gp_offset13.pre, %for.body9.lr.ph ], [ %gp_offset1337, %vaarg.end21 ]
+  %result.131 = phi i32 [ %add, %for.body9.lr.ph ], [ %add23, %vaarg.end21 ]
+  %i.130 = phi i32 [ 0, %for.body9.lr.ph ], [ %inc25, %vaarg.end21 ]
+  %fits_in_gp14 = icmp ult i32 %gp_offset13, 41
+  br i1 %fits_in_gp14, label %vaarg.in_reg15, label %vaarg.in_mem17
+
+vaarg.in_reg15:                                   ; preds = %for.body9
+  %reg_save_area16 = load i8** %5, align 16
+  %6 = sext i32 %gp_offset13 to i64
+  %7 = getelementptr i8* %reg_save_area16, i64 %6
+  %8 = add i32 %gp_offset13, 8
+  store i32 %8, i32* %gp_offset_p12, align 16
+  br label %vaarg.end21
+
+vaarg.in_mem17:                                   ; preds = %for.body9
+  %overflow_arg_area19 = load i8** %overflow_arg_area_p18, align 8
+  %overflow_arg_area.next20 = getelementptr i8* %overflow_arg_area19, i64 8
+  store i8* %overflow_arg_area.next20, i8** %overflow_arg_area_p18, align 8
+  br label %vaarg.end21
+
+vaarg.end21:                                      ; preds = %vaarg.in_mem17, %vaarg.in_reg15
+  %gp_offset1337 = phi i32 [ %8, %vaarg.in_reg15 ], [ %gp_offset13, %vaarg.in_mem17 ]
+  %vaarg.addr22.in = phi i8* [ %7, %vaarg.in_reg15 ], [ %overflow_arg_area19, %vaarg.in_mem17 ]
+  %vaarg.addr22 = bitcast i8* %vaarg.addr22.in to i32*
+  %9 = load i32* %vaarg.addr22, align 4
+  %add23 = add nsw i32 %9, %result.131
+  %inc25 = add nsw i32 %i.130, 1
+  %exitcond = icmp eq i32 %inc25, %n
+  br i1 %exitcond, label %for.end26, label %for.body9
+
+for.end26:                                        ; preds = %vaarg.end21, %for.end, %for.end.thread
+  %result.1.lcssa = phi i32 [ %add, %for.end ], [ 0, %for.end.thread ], [ %add23, %vaarg.end21 ]
+  call void @llvm.va_end(i8* %arraydecay1)
+  ret i32 %result.1.lcssa
+}
+
+declare void @llvm.va_start(i8*) nounwind
+
+declare void @llvm.va_end(i8*) nounwind
+
+define i32 @main() nounwind uwtable {
+entry:
+  %call = tail call i32 (i32, ...)* @sum(i32 5, i32 1, i32 2, i32 3, i32 4, i32 5)
+  %call1 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 %call) nounwind
+  ret i32 0
+}
+
+declare i32 @printf(i8* nocapture, ...) nounwind





More information about the llvm-commits mailing list