[CodeGen][IfCvt] Don't re-ifcvt blocks with unanalyzable terminators.
authorAhmed Bougacha <ahmed.bougacha@gmail.com>
Sat, 21 Mar 2015 01:23:15 +0000 (01:23 +0000)
committerAhmed Bougacha <ahmed.bougacha@gmail.com>
Sat, 21 Mar 2015 01:23:15 +0000 (01:23 +0000)
If we couldn't analyze its terminator (i.e., it's an indirectbr, or some
other weirdness), we can't safely re-if-convert a predicated block,
because we can't tell whether the predicated terminator can
fallthrough (it does).

Currently, we would completely ignore the fallthrough successor. In
the added testcase, this means we used to generate:

    ...
  @ %entry:
    cmp   r5, #21
    ittt  ne
  @ %cc1f:
    cmpne r7, #42
  @ %cc2t:
    strne.w       r5, [r8]
    movne pc, r10
  @ %cc1t:
    ...

Whereas the successor of %cc1f was originally %bb1.
With the fix, we get the correct:

    ...
  @ %entry:
    cmp   r5, #21
    itt   eq
  @ %cc1t:
    streq.w       r5, [r11]
    moveq pc, r0
  @ %cc1f:
    cmp   r7, #42
    itt   ne
  @ %cc2t:
    strne.w       r5, [r8]
    movne pc, r10
  @ %bb1:
    ...

rdar://20192768
Differential Revision: http://reviews.llvm.org/D8509

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

lib/CodeGen/IfConversion.cpp
test/CodeGen/ARM/ifcvt-iter-indbr.ll [new file with mode: 0644]

index 2395f32061d911c205e01dc6169cb2ac968d435d..b8799a563fcb4a1fda98249b9c26b3a94a3ec7bf 100644 (file)
@@ -726,6 +726,12 @@ bool IfConverter::FeasibilityAnalysis(BBInfo &BBI,
   if (BBI.IsDone || BBI.IsUnpredicable)
     return false;
 
+  // If it is already predicated but we couldn't analyze its terminator, the
+  // latter might fallthrough, but we can't determine where to.
+  // Conservatively avoid if-converting again.
+  if (BBI.Predicate.size() && !BBI.IsBrAnalyzable)
+    return false;
+
   // If it is already predicated, check if the new predicate subsumes
   // its predicate.
   if (BBI.Predicate.size() && !TII->SubsumesPredicate(Pred, BBI.Predicate))
diff --git a/test/CodeGen/ARM/ifcvt-iter-indbr.ll b/test/CodeGen/ARM/ifcvt-iter-indbr.ll
new file mode 100644 (file)
index 0000000..75e9d77
--- /dev/null
@@ -0,0 +1,56 @@
+; RUN: llc < %s -mtriple thumbv7s-apple-darwin  -asm-verbose=false | FileCheck %s
+
+declare i32 @foo(i32)
+declare i8* @bar(i32, i8*, i8*)
+
+; Verify that we don't try to iteratively re-ifconvert a block with a
+; (predicated) indirectbr terminator.
+; If we do, we would ignore its fallthrough successor.
+
+
+; CHECK-LABEL: test:
+; CHECK:       cmp {{.*}}, #21
+; CHECK-NEXT:  itt eq
+; CHECK-NEXT:  streq.w
+; CHECK-NEXT:  moveq pc
+; CHECK-NEXT: LBB{{[0-9_]+}}:
+; CHECK-NEXT:  cmp {{.*}}, #42
+; CHECK-NEXT:  itt ne
+; CHECK-NEXT:  strne.w
+; CHECK-NEXT:  movne pc
+; CHECK-NEXT: Ltmp
+; CHECK-NEXT: LBB0_2:
+; CHECK-NEXT:  movw r0, #1234
+; CHECK-NEXT:  b [[FOOCALL:LBB[0-9_]+]]
+; CHECK-NEXT: Ltmp
+; CHECK-NEXT: LBB{{[0-9_]+}}:
+; CHECK-NEXT:  movw r0, #4567
+; CHECK-NEXT: [[FOOCALL]]:
+; CHECK-NEXT:  blx _foo
+
+define i32 @test(i32 %a, i32 %a2, i32* %p, i32* %p2) {
+entry:
+  %dst1 = call i8* @bar(i32 1, i8* blockaddress(@test, %bb1), i8* blockaddress(@test, %bb2))
+  %dst2 = call i8* @bar(i32 2, i8* blockaddress(@test, %bb1), i8* blockaddress(@test, %bb2))
+  %dst3 = call i8* @bar(i32 3, i8* blockaddress(@test, %bb1), i8* blockaddress(@test, %bb2))
+  %cc1 = icmp eq i32 %a, 21
+  br i1 %cc1, label %cc1t, label %cc1f
+
+cc1t:
+  store i32 %a, i32* %p
+  indirectbr i8* %dst3, [label %bb1, label %bb2]
+
+cc1f:
+  %cc2 = icmp ne i32 %a2, 42
+  br i1 %cc2, label %cc2t, label %bb1
+cc2t:
+  store i32 %a, i32* %p2
+  indirectbr i8* %dst1, [label %bb1, label %bb2]
+
+bb1:
+  %ret_bb1 = call i32 @foo(i32 1234)
+  ret i32 %ret_bb1
+bb2:
+  %ret_bb2 = call i32 @foo(i32 4567)
+  ret i32 %ret_bb2
+}