Fix a crash in block placement due to an inner loop that happened to be
authorChandler Carruth <chandlerc@gmail.com>
Wed, 23 Nov 2011 03:03:21 +0000 (03:03 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Wed, 23 Nov 2011 03:03:21 +0000 (03:03 +0000)
reversed in the function's original ordering, and we happened to
encounter it while handling an outer unnatural CFG structure.

Thanks to the test case reduced from GCC's source by Benjamin Kramer.
This may also fix a crasher in gzip that Duncan reduced for me, but
I haven't yet gotten to testing that one.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@145094 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/MachineBlockPlacement.cpp
test/CodeGen/X86/block-placement.ll

index 4cbc94e0b7dbbfb0d98a16bee5d266774fe23893..0d15e8a726fc4bdffa0ba632e6088b73fa530da6 100644 (file)
@@ -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;
index 8a8bf1345e94f936e4508c1159f34fe363362730..05d6f8138f9194caec8d32e6300b669c141b33da 100644 (file)
@@ -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
+}