[cfe-commits] r135033 - in /cfe/trunk: lib/CodeGen/CGClass.cpp lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/new-overflow.cpp test/CodeGenCXX/new.cpp test/CodeGenCXX/partial-destruction.cpp test/CodeGenCXX/value-init.cpp

John McCall rjmccall at apple.com
Tue Jul 12 23:10:41 PDT 2011


Author: rjmccall
Date: Wed Jul 13 01:10:41 2011
New Revision: 135033

URL: http://llvm.org/viewvc/llvm-project?rev=135033&view=rev
Log:
Convert the standard default-construction loops to use phis and
partial destruction.


Modified:
    cfe/trunk/lib/CodeGen/CGClass.cpp
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/test/CodeGenCXX/new-overflow.cpp
    cfe/trunk/test/CodeGenCXX/new.cpp
    cfe/trunk/test/CodeGenCXX/partial-destruction.cpp
    cfe/trunk/test/CodeGenCXX/value-init.cpp

Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=135033&r1=135032&r2=135033&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Wed Jul 13 01:10:41 2011
@@ -1033,73 +1033,68 @@
   }
 }
 
-/// EmitCXXAggrConstructorCall - This routine essentially creates a (nested)
-/// for-loop to call the default constructor on individual members of the
-/// array. 
-/// 'D' is the default constructor for elements of the array, 'ArrayTy' is the
-/// array type and 'ArrayPtr' points to the beginning fo the array.
-/// It is assumed that all relevant checks have been made by the caller.
+/// EmitCXXAggrConstructorCall - Emit a loop to call a particular
+/// constructor for each of several members of an array.
 ///
-/// \param ZeroInitialization True if each element should be zero-initialized
-/// before it is constructed.
+/// \param ctor the constructor to call for each element
+/// \param argBegin,argEnd the arguments to evaluate and pass to the
+///   constructor
+/// \param arrayType the type of the array to initialize
+/// \param arrayBegin an arrayType*
+/// \param zeroInitialize true if each element should be
+///   zero-initialized before it is constructed
 void
-CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
-                                            const ConstantArrayType *ArrayTy,
-                                            llvm::Value *ArrayPtr,
-                                            CallExpr::const_arg_iterator ArgBeg,
-                                            CallExpr::const_arg_iterator ArgEnd,
-                                            bool ZeroInitialization) {
-
-  const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
-  llvm::Value * NumElements =
-    llvm::ConstantInt::get(SizeTy, 
-                           getContext().getConstantArrayElementCount(ArrayTy));
+CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
+                                            const ConstantArrayType *arrayType,
+                                            llvm::Value *arrayBegin,
+                                          CallExpr::const_arg_iterator argBegin,
+                                            CallExpr::const_arg_iterator argEnd,
+                                            bool zeroInitialize) {
+  QualType elementType;
+  llvm::Value *numElements =
+    emitArrayLength(arrayType, elementType, arrayBegin);
 
-  EmitCXXAggrConstructorCall(D, NumElements, ArrayPtr, ArgBeg, ArgEnd,
-                             ZeroInitialization);
+  EmitCXXAggrConstructorCall(ctor, numElements, arrayBegin,
+                             argBegin, argEnd, zeroInitialize);
 }
 
+/// EmitCXXAggrConstructorCall - Emit a loop to call a particular
+/// constructor for each of several members of an array.
+///
+/// \param ctor the constructor to call for each element
+/// \param numElements the number of elements in the array;
+///   assumed to be non-zero
+/// \param argBegin,argEnd the arguments to evaluate and pass to the
+///   constructor
+/// \param arrayBegin a T*, where T is the type constructed by ctor
+/// \param zeroInitialize true if each element should be
+///   zero-initialized before it is constructed
 void
-CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
-                                          llvm::Value *NumElements,
-                                          llvm::Value *ArrayPtr,
-                                          CallExpr::const_arg_iterator ArgBeg,
-                                          CallExpr::const_arg_iterator ArgEnd,
-                                            bool ZeroInitialization) {
-  const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
-
-  // Create a temporary for the loop index and initialize it with 0.
-  llvm::Value *IndexPtr = CreateTempAlloca(SizeTy, "loop.index");
-  llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy);
-  Builder.CreateStore(Zero, IndexPtr);
-
-  // Start the loop with a block that tests the condition.
-  llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
-  llvm::BasicBlock *AfterFor = createBasicBlock("for.end");
-
-  EmitBlock(CondBlock);
-
-  llvm::BasicBlock *ForBody = createBasicBlock("for.body");
-
-  // Generate: if (loop-index < number-of-elements fall to the loop body,
-  // otherwise, go to the block after the for-loop.
-  llvm::Value *Counter = Builder.CreateLoad(IndexPtr);
-  llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElements, "isless");
-  // If the condition is true, execute the body.
-  Builder.CreateCondBr(IsLess, ForBody, AfterFor);
-
-  EmitBlock(ForBody);
+CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
+                                            llvm::Value *numElements,
+                                            llvm::Value *arrayBegin,
+                                         CallExpr::const_arg_iterator argBegin,
+                                           CallExpr::const_arg_iterator argEnd,
+                                            bool zeroInitialize) {
+  // Find the end of the array.
+  llvm::Value *arrayEnd = Builder.CreateInBoundsGEP(arrayBegin, numElements,
+                                                    "arrayctor.end");
+
+  // Enter the loop, setting up a phi for the current location to initialize.
+  llvm::BasicBlock *entryBB = Builder.GetInsertBlock();
+  llvm::BasicBlock *loopBB = createBasicBlock("arrayctor.loop");
+  EmitBlock(loopBB);
+  llvm::PHINode *cur = Builder.CreatePHI(arrayBegin->getType(), 2,
+                                         "arrayctor.cur");
+  cur->addIncoming(arrayBegin, entryBB);
 
-  llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc");
   // Inside the loop body, emit the constructor call on the array element.
-  Counter = Builder.CreateLoad(IndexPtr);
-  llvm::Value *Address = Builder.CreateInBoundsGEP(ArrayPtr, Counter, 
-                                                   "arrayidx");
+
+  QualType type = getContext().getTypeDeclType(ctor->getParent());
 
   // Zero initialize the storage, if requested.
-  if (ZeroInitialization)
-    EmitNullInitialization(Address, 
-                           getContext().getTypeDeclType(D->getParent()));
+  if (zeroInitialize)
+    EmitNullInitialization(cur, type);
   
   // C++ [class.temporary]p4: 
   // There are two contexts in which temporaries are destroyed at a different
@@ -1109,27 +1104,33 @@
   // every temporary created in a default argument expression is sequenced 
   // before the construction of the next array element, if any.
   
-  // Keep track of the current number of live temporaries.
   {
     RunCleanupsScope Scope(*this);
 
-    EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase=*/false, Address,
-                           ArgBeg, ArgEnd);
-  }
-
-  EmitBlock(ContinueBlock);
+    // Evaluate the constructor and its arguments in a regular
+    // partial-destroy cleanup.
+    if (getLangOptions().Exceptions &&
+        !ctor->getParent()->hasTrivialDestructor()) {
+      Destroyer *destroyer = destroyCXXObject;
+      pushRegularPartialArrayCleanup(arrayBegin, cur, type, *destroyer);
+    }
 
-  // Emit the increment of the loop counter.
-  llvm::Value *NextVal = llvm::ConstantInt::get(SizeTy, 1);
-  Counter = Builder.CreateLoad(IndexPtr);
-  NextVal = Builder.CreateAdd(Counter, NextVal, "inc");
-  Builder.CreateStore(NextVal, IndexPtr);
+    EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/ false,
+                           cur, argBegin, argEnd);
+  }
 
-  // Finally, branch back up to the condition for the next iteration.
-  EmitBranch(CondBlock);
+  // Go to the next element.
+  llvm::Value *next =
+    Builder.CreateInBoundsGEP(cur, llvm::ConstantInt::get(SizeTy, 1),
+                              "arrayctor.next");
+  cur->addIncoming(next, Builder.GetInsertBlock());
+
+  // Check whether that's the end of the loop.
+  llvm::Value *done = Builder.CreateICmpEQ(next, arrayEnd, "arrayctor.done");
+  llvm::BasicBlock *contBB = createBasicBlock("arrayctor.cont");
+  Builder.CreateCondBr(done, contBB, loopBB);
 
-  // Emit the fall-through block.
-  EmitBlock(AfterFor, true);
+  EmitBlock(contBB);
 }
 
 void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF,

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=135033&r1=135032&r2=135033&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Wed Jul 13 01:10:41 2011
@@ -379,19 +379,11 @@
     }
   }
   
-  const ConstantArrayType *Array 
-    = getContext().getAsConstantArrayType(E->getType());
-  if (Array) {
-    QualType BaseElementTy = getContext().getBaseElementType(Array);
-    const llvm::Type *BasePtr = ConvertType(BaseElementTy);
-    BasePtr = llvm::PointerType::getUnqual(BasePtr);
-    llvm::Value *BaseAddrPtr =
-      Builder.CreateBitCast(Dest.getAddr(), BasePtr);
-    
-    EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr, 
+  if (const ConstantArrayType *arrayType 
+        = getContext().getAsConstantArrayType(E->getType())) {
+    EmitCXXAggrConstructorCall(CD, arrayType, Dest.getAddr(), 
                                E->arg_begin(), E->arg_end());
-  }
-  else {
+  } else {
     CXXCtorType Type = Ctor_Complete;
     bool ForVirtualBase = false;
 
@@ -805,11 +797,37 @@
 
         RequiresZeroInitialization = true;
       }
+
+      // It's legal for NumElements to be zero, but
+      // EmitCXXAggrConstructorCall doesn't handle that, so we need to.
+      llvm::BranchInst *br = 0;
+
+      // Optimize for a constant count.
+      llvm::ConstantInt *constantCount
+        = dyn_cast<llvm::ConstantInt>(NumElements);
+      if (constantCount) {
+        // Just skip out if the constant count is zero.
+        if (constantCount->isZero()) return;
+
+      // Otherwise, emit the check.
+      } else {
+        llvm::BasicBlock *loopBB = CGF.createBasicBlock("new.ctorloop");
+        llvm::Value *iszero = CGF.Builder.CreateIsNull(NumElements, "isempty");
+        br = CGF.Builder.CreateCondBr(iszero, loopBB, loopBB);
+        CGF.EmitBlock(loopBB);
+      }
       
       CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr, 
                                      E->constructor_arg_begin(), 
                                      E->constructor_arg_end(),
                                      RequiresZeroInitialization);
+
+      // Patch the earlier check to skip over the loop.
+      if (br) {
+        assert(CGF.Builder.GetInsertBlock()->empty());
+        br->setSuccessor(0, CGF.Builder.GetInsertBlock());
+      }
+
       return;
     } else if (E->getNumConstructorArgs() == 1 &&
                isa<ImplicitValueInitExpr>(E->getConstructorArg(0))) {

Modified: cfe/trunk/test/CodeGenCXX/new-overflow.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/new-overflow.cpp?rev=135033&r1=135032&r2=135033&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/new-overflow.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/new-overflow.cpp Wed Jul 13 01:10:41 2011
@@ -18,7 +18,7 @@
   // CHECK-NEXT: [[T2:%.*]] = extractvalue { i32, i1 } [[T0]], 0
   // CHECK-NEXT: [[T3:%.*]] = select i1 [[T1]], i32 -1, i32 [[T2]]
   // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T3]])
-  // CHECK:      icmp ult i32 {{.*}}, [[N]]
+  // CHECK:      getelementptr inbounds {{.*}}, i32 [[N]]
   elt *test(short s) {
     return new elt[s];
   }
@@ -41,7 +41,7 @@
   // CHECK-NEXT: [[T3:%.*]] = mul i32 [[N]], 100
   // CHECK-NEXT: [[T4:%.*]] = select i1 [[T1]], i32 -1, i32 [[T2]]
   // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T4]])
-  // CHECK:      icmp ult i32 {{.*}}, [[T3]]
+  // CHECK:      getelementptr inbounds {{.*}}, i32 [[T3]]
   elt *test(short s) {
     return new elt[s];
   }
@@ -69,7 +69,7 @@
   // CHECK-NEXT: [[T7:%.*]] = extractvalue { i32, i1 } [[T4]], 0
   // CHECK-NEXT: [[T8:%.*]] = select i1 [[T6]], i32 -1, i32 [[T7]]
   // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T8]])
-  // CHECK:      icmp ult i32 {{.*}}, [[T3]]
+  // CHECK:      getelementptr inbounds {{.*}}, i32 [[T3]]
   elt *test(short s) {
     return new elt[s];
   }
@@ -88,7 +88,7 @@
   // CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[N]], 0
   // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 -1, i32 [[N]]
   // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T1]])
-  // CHECK:      icmp ult i32 {{.*}}, [[N]]
+  // CHECK:      getelementptr inbounds {{.*}}, i32 [[N]]
   elt *test(short s) {
     return new elt[s];
   }
@@ -107,7 +107,7 @@
   // CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[N]], 0
   // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 -1, i32 [[N]]
   // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T1]])
-  // CHECK:      icmp ult i32 {{.*}}, [[N]]
+  // CHECK:      getelementptr inbounds {{.*}}, i32 [[N]]
   elt *test(int s) {
     return new elt[s];
   }
@@ -129,7 +129,7 @@
   // CHECK-NEXT: [[T2:%.*]] = extractvalue { i32, i1 } [[T0]], 0
   // CHECK-NEXT: [[T3:%.*]] = select i1 [[T1]], i32 -1, i32 [[T2]]
   // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T3]])
-  // CHECK:      icmp ult i32 {{.*}}, [[N]]
+  // CHECK:      getelementptr inbounds {{.*}}, i32 [[N]]
   elt *test(unsigned short s) {
     return new elt[s];
   }
@@ -152,7 +152,7 @@
   // CHECK-NEXT: [[T3:%.*]] = mul i32 [[N]], 100
   // CHECK-NEXT: [[T4:%.*]] = select i1 [[T1]], i32 -1, i32 [[T2]]
   // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T4]])
-  // CHECK:      icmp ult i32 {{.*}}, [[T3]]
+  // CHECK:      getelementptr inbounds {{.*}}, i32 [[T3]]
   elt *test(unsigned short s) {
     return new elt[s];
   }
@@ -177,7 +177,7 @@
   // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T2]], 0
   // CHECK-NEXT: [[T6:%.*]] = select i1 [[T4]], i32 -1, i32 [[T5]]
   // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T6]])
-  // CHECK:      icmp ult i32 {{.*}}, [[T1]]
+  // CHECK:      getelementptr inbounds {{.*}}, i32 [[T1]]
   elt *test(long long s) {
     return new elt[s];
   }
@@ -202,7 +202,7 @@
   // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T2]], 0
   // CHECK-NEXT: [[T6:%.*]] = select i1 [[T4]], i32 -1, i32 [[T5]]
   // CHECK-NEXT: call noalias i8* @_Znaj(i32 [[T6]])
-  // CHECK:      icmp ult i32 {{.*}}, [[T1]]
+  // CHECK:      getelementptr inbounds {{.*}}, i32 [[T1]]
   elt *test(unsigned long long s) {
     return new elt[s];
   }

Modified: cfe/trunk/test/CodeGenCXX/new.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/new.cpp?rev=135033&r1=135032&r2=135033&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/new.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/new.cpp Wed Jul 13 01:10:41 2011
@@ -182,12 +182,17 @@
   }
 
   // CHECK:    define void @_ZN6test155test1EPv(
-  // CHECK:      [[P:%.*]] = load i8*
+  // CHECK:      [[P:%.*]] = load i8**
   // CHECK-NEXT: icmp eq i8* [[P]], null
   // CHECK-NEXT: br i1
-  // CHECK:      [[T0:%.*]] = bitcast i8* [[P]] to [[A:%.*]]*
-  // CHECK:      [[T1:%.*]] = getelementptr inbounds [[A]]* [[T0]],
-  // CHECK-NEXT: call void @_ZN6test151AC1Ev([[A]]* [[T1]])
+  // CHECK:      [[BEGIN:%.*]] = bitcast i8* [[P]] to [[A:%.*]]*
+  // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]]* [[BEGIN]], i64 5
+  // CHECK-NEXT: br label
+  // CHECK:      [[CUR:%.*]] = phi [[A]]* [ [[BEGIN]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ]
+  // CHECK-NEXT: call void @_ZN6test151AC1Ev([[A]]* [[CUR]])
+  // CHECK-NEXT: [[NEXT]] = getelementptr inbounds [[A]]* [[CUR]], i64 1
+  // CHECK-NEXT: [[DONE:%.*]] = icmp eq [[A]]* [[NEXT]], [[END]]
+  // CHECK-NEXT: br i1 [[DONE]]
   void test1(void *p) {
     new (p) A[5];
   }
@@ -202,9 +207,13 @@
   // CHECK-NEXT: [[P:%.*]] = load i8*
   // CHECK-NEXT: icmp eq i8* [[P]], null
   // CHECK-NEXT: br i1
-  // CHECK:      [[T0:%.*]] = bitcast i8* [[P]] to [[A:%.*]]*
-  // CHECK:      [[T1:%.*]] = getelementptr inbounds [[A]]* [[T0]],
-  // CHECK-NEXT: call void @_ZN6test151AC1Ev([[A]]* [[T1]])
+  // CHECK:      [[BEGIN:%.*]] = bitcast i8* [[P]] to [[A:%.*]]*
+  // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq i64 [[T0]], 0
+  // CHECK-NEXT: br i1 [[ISEMPTY]],
+  // CHECK:      [[END:%.*]] = getelementptr inbounds [[A]]* [[BEGIN]], i64 [[T0]]
+  // CHECK-NEXT: br label
+  // CHECK:      [[CUR:%.*]] = phi [[A]]* [ [[BEGIN]],
+  // CHECK-NEXT: call void @_ZN6test151AC1Ev([[A]]* [[CUR]])
   void test2(void *p, int n) {
     new (p) A[n];
   }

Modified: cfe/trunk/test/CodeGenCXX/partial-destruction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/partial-destruction.cpp?rev=135033&r1=135032&r2=135033&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/partial-destruction.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/partial-destruction.cpp Wed Jul 13 01:10:41 2011
@@ -118,3 +118,38 @@
   // CHECK:      invoke void @_ZN5test11AD1Ev([[A]]* [[Y]])
   // CHECK:      invoke void @_ZN5test11AD1Ev([[A]]* [[X]])
 }
+
+namespace test2 {
+  struct A { A(); ~A(); };
+
+  void test() {
+    A v[4][7];
+
+    // CHECK:    define void @_ZN5test24testEv()
+    // CHECK:      [[V:%.*]] = alloca [4 x [7 x [[A:%.*]]]], align 1
+    // CHECK-NEXT: alloca i8*
+    // CHECK-NEXT: alloca i32
+    // CHECK-NEXT: alloca i32
+
+    // Main initialization loop.
+    // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [4 x [7 x [[A]]]]* [[V]], i32 0, i32 0, i32 0
+    // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]]* [[BEGIN]], i64 28
+    // CHECK-NEXT: br label
+    // CHECK:      [[CUR:%.*]] = phi [[A]]* [ [[BEGIN]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ]
+    // CHECK-NEXT: invoke void @_ZN5test21AC1Ev([[A]]* [[CUR]])
+    // CHECK:      [[NEXT:%.*]] = getelementptr inbounds [[A]]* [[CUR]], i64 1
+    // CHECK-NEXT: [[DONE:%.*]] = icmp eq [[A]]* [[NEXT]], [[END]]
+    // CHECK-NEXT: br i1 [[DONE]],
+
+    // Partial destruction landing pad.
+    // CHECK:      llvm.eh.exception()
+    // CHECK:      [[EMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[CUR]]
+    // CHECK-NEXT: br i1 [[EMPTY]],
+    // CHECK:      [[PAST:%.*]] = phi [[A]]* [ [[CUR]], {{%.*}} ], [ [[DEL:%.*]], {{%.*}} ]
+    // CHECK-NEXT: [[DEL]] = getelementptr inbounds [[A]]* [[PAST]], i64 -1
+    // CHECK-NEXT: invoke void @_ZN5test21AD1Ev([[A]]* [[DEL]])
+    // CHECK:      [[T0:%.*]] = icmp eq [[A]]* [[DEL]], [[BEGIN]]
+    // CHECK-NEXT: br i1 [[T0]],
+  }
+
+}

Modified: cfe/trunk/test/CodeGenCXX/value-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/value-init.cpp?rev=135033&r1=135032&r2=135033&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/value-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/value-init.cpp Wed Jul 13 01:10:41 2011
@@ -204,7 +204,6 @@
   };
   // CHECK:    define void @_ZN5test64testEv()
   // CHECK:      [[ARR:%.*]] = alloca [10 x [20 x [[A:%.*]]]],
-  // CHECK-NEXT: [[IDX:%.*]] = alloca i64
 
   // CHECK-NEXT: [[INNER:%.*]] = getelementptr inbounds [10 x [20 x [[A]]]]* [[ARR]], i64 0, i64 0
   // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [20 x [[A]]]* [[INNER]], i64 0, i64 0
@@ -222,23 +221,17 @@
   // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [20 x [[A]]]* [[INNER]], i64 10
   // CHECK-NEXT: br label
   // CHECK:      [[CUR:%.*]] = phi [20 x [[A]]]* [ [[BEGIN]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ]
-  // CHECK-NEXT: [[FIRST:%.*]] = bitcast [20 x [[A]]]* [[CUR]] to [[A]]*
 
-  // TODO: this loop should use phis, too, and for preference would be
-  // merged with the outer loop.
-  // CHECK-NEXT: store i64 0, i64* [[IDX]]
-  // CHECK-NEXT: br label
-  // CHECK:      [[T0:%.*]] = load i64* [[IDX]]
-  // CHECK-NEXT: [[T1:%.*]] = icmp ult i64 [[T0]], 20
-  // CHECK-NEXT: br i1 [[T1]]
-  // CHECK:      [[T0:%.*]] = load i64* [[IDX]]
-  // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[A]]* [[FIRST]], i64 [[T0]]
-  // CHECK-NEXT: call void @_ZN5test61AC1Ev([[A]]* [[T1]])
-  // CHECK-NEXT: br label
-  // CHECK:      [[T0:%.*]] = load i64* [[IDX]]
-  // CHECK-NEXT: [[T1:%.*]] = add i64 [[T0]], 1
-  // CHECK-NEXT: store i64 [[T1]], i64* [[IDX]]
+  // Inner loop.
+  // CHECK-NEXT: [[IBEGIN:%.*]] = getelementptr inbounds [20 x [[A]]]* [[CUR]], i32 0, i32 0
+  // CHECK-NEXT: [[IEND:%.*]] = getelementptr inbounds [[A]]* [[IBEGIN]], i64 20
   // CHECK-NEXT: br label
+  // CHECK:      [[ICUR:%.*]] = phi [[A]]* [ [[IBEGIN]], {{%.*}} ], [ [[INEXT:%.*]], {{%.*}} ]
+  // CHECK-NEXT: call void @_ZN5test61AC1Ev([[A]]* [[ICUR]])
+  // CHECK-NEXT: [[INEXT:%.*]] = getelementptr inbounds [[A]]* [[ICUR]], i64 1
+  // CHECK-NEXT: [[T0:%.*]] = icmp eq [[A]]* [[INEXT]], [[IEND]]
+  // CHECK-NEXT: br i1 [[T0]],
+
   // CHECK:      [[NEXT]] = getelementptr inbounds [20 x [[A]]]* [[CUR]], i64 1
   // CHECK-NEXT: [[T0:%.*]] = icmp eq [20 x [[A]]]* [[NEXT]], [[END]]
   // CHECK-NEXT: br i1 [[T0]]





More information about the cfe-commits mailing list