prevent jump threading from merging blocks when their address is

taken (and used!).  This prevents merging the blocks (invalidating
the block addresses) in a case like this:

#define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })

void foo() {
  printf("%p\n", _THIS_IP_);
  printf("%p\n", _THIS_IP_);
  printf("%p\n", _THIS_IP_);
}

which fixes PR4151.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125829 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2011-02-18 04:43:06 +00:00
parent 13fb0db0c2
commit 78f7a25f98
2 changed files with 45 additions and 2 deletions

View File

@ -606,6 +606,16 @@ static unsigned GetBestDestForJumpOnUndef(BasicBlock *BB) {
return MinSucc;
}
static bool hasAddressTakenAndUsed(BasicBlock *BB) {
if (!BB->hasAddressTaken()) return false;
// If the block has its address taken, it may be a tree of dead constants
// hanging off of it. These shouldn't keep the block alive.
BlockAddress *BA = BlockAddress::get(BB);
BA->removeDeadConstantUsers();
return !BA->use_empty();
}
/// ProcessBlock - If there are any predecessors whose control can be threaded
/// through to a successor, transform them now.
bool JumpThreading::ProcessBlock(BasicBlock *BB) {
@ -621,7 +631,7 @@ bool JumpThreading::ProcessBlock(BasicBlock *BB) {
// predecessors of our predecessor block.
if (BasicBlock *SinglePred = BB->getSinglePredecessor()) {
if (SinglePred->getTerminator()->getNumSuccessors() == 1 &&
SinglePred != BB) {
SinglePred != BB && !hasAddressTakenAndUsed(BB)) {
// If SinglePred was a loop header, BB becomes one.
if (LoopHeaders.erase(SinglePred))
LoopHeaders.insert(BB);

View File

@ -44,7 +44,9 @@ indirectgoto: ; preds = %if.else, %entry
; Check constant folding of indirectbr
; CHECK: void @test2
; CHECK-NEXT: :
; CHECK: entry:
; CHECK-NEXT: br label %L1
; CHECK: L1:
; CHECK-NEXT: call void @bar
; CHECK-NEXT: ret void
define void @test2() nounwind {
@ -59,3 +61,34 @@ L2: ; preds = %indirectgoto
call void @baz()
ret void
}
; PR4151
; Don't merge address-taken blocks.
@.str = private unnamed_addr constant [4 x i8] c"%p\0A\00"
; CHECK: @test3
; CHECK: __here:
; CHECK: blockaddress(@test3, %__here)
; CHECK: __here1:
; CHECK: blockaddress(@test3, %__here1)
; CHECK: __here3:
; CHECK: blockaddress(@test3, %__here3)
define void @test3() nounwind ssp noredzone {
entry:
br label %__here
__here: ; preds = %entry
%call = call i32 (...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i64 ptrtoint (i8* blockaddress(@test3, %__here) to i64)) nounwind noredzone
br label %__here1
__here1: ; preds = %__here
%call2 = call i32 (...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i64 ptrtoint (i8* blockaddress(@test3, %__here1) to i64)) nounwind noredzone
br label %__here3
__here3: ; preds = %__here1
%call4 = call i32 (...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i64 ptrtoint (i8* blockaddress(@test3, %__here3) to i64)) nounwind noredzone
ret void
}
declare i32 @printf(...) noredzone