[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