aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-07-20 21:07:09 +0000
committerChris Lattner <sabre@nondot.org>2010-07-20 21:07:09 +0000
commit83252dcfe61aaebcb6bc117e71dc12968729513f (patch)
treea303b42463464aef9a146dbc5678a70d0c0bfe31
parent021a7a63984f0f912dc9e9dae2a1b3e1509a40ce (diff)
Follow the implementation approach suggested by PR6687,
which generates more efficient and more obviously conformant code. We now test for overflow of the multiply then force the result to -1 if so. On X86, this generates nice code like this: __Z4testl: ## @_Z4testl ## BB#0: ## %entry subl $12, %esp movl $4, %eax mull 16(%esp) testl %edx, %edx movl $-1, %ecx cmovel %eax, %ecx movl %ecx, (%esp) call __Znam addl $12, %esp ret git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108927 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGExprCXX.cpp21
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp40
-rw-r--r--lib/CodeGen/CodeGenFunction.h6
-rw-r--r--test/CodeGenCXX/operator-new.cpp7
4 files changed, 21 insertions, 53 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index cc34b3d75c..d3e7919224 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -440,7 +440,7 @@ static llvm::Value *EmitCXXNewAllocSize(ASTContext &Context,
// new double[n]
// where n is 2^30 on a 32-bit machine or 2^62 on a 64-bit machine. Because
// of this, we need to detect the overflow and ensure that an exception is
- // called by invoking std::__throw_length_error.
+ // called by forcing the size to -1 on overflow.
llvm::Value *UMulF = CGF.CGM.getIntrinsic(llvm::Intrinsic::umul_with_overflow,
&SizeTy, 1);
llvm::Value *MulRes = CGF.Builder.CreateCall2(UMulF, NumElements,
@@ -448,15 +448,26 @@ static llvm::Value *EmitCXXNewAllocSize(ASTContext &Context,
TypeSize.getQuantity()));
// Branch on the overflow bit to the overflow block, which is lazily created.
llvm::Value *DidOverflow = CGF.Builder.CreateExtractValue(MulRes, 1);
+ // Get the normal result of the multiplication.
+ llvm::Value *V = CGF.Builder.CreateExtractValue(MulRes, 0);
llvm::BasicBlock *NormalBB = CGF.createBasicBlock("no_overflow");
+ llvm::BasicBlock *OverflowBB = CGF.createBasicBlock("overflow");
- CGF.Builder.CreateCondBr(DidOverflow, CGF.getThrowLengthErrorBB(), NormalBB);
+ CGF.Builder.CreateCondBr(DidOverflow, OverflowBB, NormalBB);
+
+ llvm::BasicBlock *PrevBB = CGF.Builder.GetInsertBlock();
+
+ // We just need the overflow block to build a PHI node.
+ CGF.EmitBlock(OverflowBB);
CGF.EmitBlock(NormalBB);
- // Get the normal result of the multiplication.
- llvm::Value *V = CGF.Builder.CreateExtractValue(MulRes, 0);
-
+ llvm::PHINode *PN = CGF.Builder.CreatePHI(V->getType());
+
+ PN->addIncoming(V, PrevBB);
+ PN->addIncoming(llvm::Constant::getAllOnesValue(V->getType()), OverflowBB);
+ V = PN;
+
// And add the cookie padding if necessary.
if (!CookiePadding.isZero())
V = CGF.Builder.CreateAdd(V,
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 5e5e2a49cc..eb6c4361be 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -36,7 +36,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
DidCallStackSave(false), UnreachableBlock(0),
CXXThisDecl(0), CXXThisValue(0), CXXVTTDecl(0), CXXVTTValue(0),
ConditionalBranchLevel(0), TerminateLandingPad(0), TerminateHandler(0),
- TrapBB(0), ThrowLengthErrorBB(0) {
+ TrapBB(0) {
// Get some frequently used types.
LLVMPointerWidth = Target.getPointerWidth(0);
@@ -155,13 +155,6 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
Builder.ClearInsertionPoint();
}
- // If someone called operator new[] and needs a throw_length_error block, emit
- // it at the end of the function.
- if (ThrowLengthErrorBB) {
- EmitBlock(ThrowLengthErrorBB);
- Builder.ClearInsertionPoint();
- }
-
// Remove the AllocaInsertPt instruction, which is just a convenience for us.
llvm::Instruction *Ptr = AllocaInsertPt;
AllocaInsertPt = 0;
@@ -185,37 +178,6 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
EmitDeclMetadata();
}
-/// getThrowLengthErrorBB - Create a basic block that will call
-/// std::__throw_length_error to throw a std::length_error exception.
-llvm::BasicBlock *CodeGenFunction::getThrowLengthErrorBB() {
- if (ThrowLengthErrorBB) return ThrowLengthErrorBB;
-
- llvm::IRBuilder<>::InsertPoint SavedIP = Builder.saveIP();
-
- ThrowLengthErrorBB = createBasicBlock("throw_length_error");
- Builder.SetInsertPoint(ThrowLengthErrorBB);
-
- // Call to void std::__throw_length_error("length_error");
- const llvm::Type *ResultType = Builder.getVoidTy();
- const llvm::Type *PtrToInt8Ty = Builder.getInt8PtrTy();
- std::vector<const llvm::Type*> ArgTys(1, PtrToInt8Ty);
- llvm::Constant *Fn =
- CGM.CreateRuntimeFunction(llvm::FunctionType::get(ResultType, ArgTys, false),
- "_ZSt20__throw_length_errorPKc");
-
- llvm::Value *C = CGM.GetAddrOfConstantCString("length_error");
- C = Builder.CreateStructGEP(C, 0, "arraydecay");
- llvm::CallInst *TheCall = Builder.CreateCall(Fn, C);
- TheCall->setDoesNotReturn();
-
- Builder.CreateUnreachable();
-
-
- Builder.restoreIP(SavedIP);
- return ThrowLengthErrorBB;
-}
-
-
/// ShouldInstrumentFunction - Return true if the current function should be
/// instrumented with __cyg_profile_func_* calls
bool CodeGenFunction::ShouldInstrumentFunction() {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 1a117cab96..f236eb4253 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -656,7 +656,7 @@ private:
llvm::BasicBlock *TerminateLandingPad;
llvm::BasicBlock *TerminateHandler;
- llvm::BasicBlock *TrapBB, *ThrowLengthErrorBB;
+ llvm::BasicBlock *TrapBB;
public:
CodeGenFunction(CodeGenModule &cgm);
@@ -1544,10 +1544,6 @@ public:
/// generate a branch around the created basic block as necessary.
llvm::BasicBlock *getTrapBB();
- /// getThrowLengthErrorBB - Create a basic block that will call
- /// std::__throw_length_error to throw a std::length_error exception.
- llvm::BasicBlock *getThrowLengthErrorBB();
-
/// EmitCallArg - Emit a single call argument.
RValue EmitCallArg(const Expr *E, QualType ArgType);
diff --git a/test/CodeGenCXX/operator-new.cpp b/test/CodeGenCXX/operator-new.cpp
index f5cb2fb6c5..b108d27ab9 100644
--- a/test/CodeGenCXX/operator-new.cpp
+++ b/test/CodeGenCXX/operator-new.cpp
@@ -23,9 +23,8 @@ void *f2(long N) {
// SANE: call{{.*}}@llvm.umul.with.overflow
// SANE: extractvalue
-// SANE: br i1{{.*}}, label %throw_length_error, label %no_overflow
+// SANE: br i1{{.*}}, label %overflow, label %no_overflow
-// SANE: throw_length_error:
-// SANE: call void @_ZSt20__throw_length_errorPKc
-// SANE: unreachable
+// SANE: = phi {{.*}} [ {{.*}}, %entry ], [ -1, %overflow ]
+// SANE: call noalias i8* @_Znaj(
}