summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/MachineBlockPlacement.cpp5
-rw-r--r--test/CodeGen/X86/block-placement.ll41
2 files changed, 45 insertions, 1 deletions
diff --git a/lib/CodeGen/MachineBlockPlacement.cpp b/lib/CodeGen/MachineBlockPlacement.cpp
index 4cbc94e0b7..0d15e8a726 100644
--- a/lib/CodeGen/MachineBlockPlacement.cpp
+++ b/lib/CodeGen/MachineBlockPlacement.cpp
@@ -488,7 +488,10 @@ MachineBasicBlock *MachineBlockPlacement::getFirstUnplacedBlock(
continue;
if (BlockToChain[I] != &PlacedChain) {
PrevUnplacedBlockIt = I;
- return I;
+ // Now select the head of the chain to which the unplaced block belongs
+ // as the block to place. This will force the entire chain to be placed,
+ // and satisfies the requirements of merging chains.
+ return *BlockToChain[I]->begin();
}
}
return 0;
diff --git a/test/CodeGen/X86/block-placement.ll b/test/CodeGen/X86/block-placement.ll
index 8a8bf1345e..05d6f8138f 100644
--- a/test/CodeGen/X86/block-placement.ll
+++ b/test/CodeGen/X86/block-placement.ll
@@ -503,3 +503,44 @@ lpad:
loop:
br label %loop
}
+
+define void @test_unnatural_cfg_backwards_inner_loop() {
+; Test that when we encounter an unnatural CFG structure after having formed
+; a chain for an inner loop which happened to be laid out backwards we don't
+; attempt to merge onto the wrong end of the inner loop just because we find it
+; first. This was reduced from a crasher in GCC's single source.
+;
+; CHECK: test_unnatural_cfg_backwards_inner_loop
+; CHECK: %entry
+; CHECK: %body
+; CHECK: %loop1
+; CHECK: %loop2b
+; CHECK: %loop2a
+
+entry:
+ br i1 undef, label %loop2a, label %body
+
+body:
+ br label %loop2a
+
+loop1:
+ %next.load = load i32** undef
+ br i1 %comp.a, label %loop2a, label %loop2b
+
+loop2a:
+ %var = phi i32* [ null, %entry ], [ null, %body ], [ %next.phi, %loop1 ]
+ %next.var = phi i32* [ null, %entry ], [ undef, %body ], [ %next.load, %loop1 ]
+ %comp.a = icmp eq i32* %var, null
+ br label %loop3
+
+loop2b:
+ %gep = getelementptr inbounds i32* %var.phi, i32 0
+ %next.ptr = bitcast i32* %gep to i32**
+ store i32* %next.phi, i32** %next.ptr
+ br label %loop3
+
+loop3:
+ %var.phi = phi i32* [ %next.phi, %loop2b ], [ %var, %loop2a ]
+ %next.phi = phi i32* [ %next.load, %loop2b ], [ %next.var, %loop2a ]
+ br label %loop1
+}