[llvm] ea817d7 - [SimplifyCFG] Look for control flow changes instead of side effects.

Teresa Johnson via llvm-commits llvm-commits at lists.llvm.org
Mon May 3 13:32:39 PDT 2021


Author: Teresa Johnson
Date: 2021-05-03T13:32:22-07:00
New Revision: ea817d79be2686d1d5fad04d429dbe392ee22b5f

URL: https://github.com/llvm/llvm-project/commit/ea817d79be2686d1d5fad04d429dbe392ee22b5f
DIFF: https://github.com/llvm/llvm-project/commit/ea817d79be2686d1d5fad04d429dbe392ee22b5f.diff

LOG: [SimplifyCFG] Look for control flow changes instead of side effects.

When passingValueIsAlwaysUndefined scans for an instruction between an
inst with a null or undef argument and its first use, it was checking
for instructions that may have side effects, which is a superset of the
instructions it intended to find (as per the comments, control flow
changing instructions that would prevent reaching the uses). Switch
to using isGuaranteedToTransferExecutionToSuccessor() instead.

Without this change, when enabling -fwhole-program-vtables, which causes
assumes to be inserted by clang, we can get different simplification
decisions. In particular, when building with instrumentation FDO it can
affect the optimizations decisions before FDO matching, leading to some
mismatches.

I had to modify d83507-knowledge-retention-bug.ll since this fix enables
more aggressive optimization of that code such that it no longer tested
the original bug it was meant to test. I removed the undef which still
provokes the original failure (confirmed by temporarily reverting the
fix) and also changed it to just invoke the passes of interest to narrow
the testing.

Similarly I needed to adjust code for UnreachableEliminate.ll to avoid
an undef which was causing the function body to get optimized away with
this fix.

Differential Revision: https://reviews.llvm.org/D101507

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/SimplifyCFG.cpp
    llvm/test/CodeGen/Thumb2/LowOverheadLoops/while-loops.ll
    llvm/test/Transforms/PhaseOrdering/d83507-knowledge-retention-bug.ll
    llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 31c50f459898..836ab432271e 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6627,9 +6627,12 @@ static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValu
     for (BasicBlock::iterator
              i = ++BasicBlock::iterator(I),
              UI = BasicBlock::iterator(dyn_cast<Instruction>(Use));
-         i != UI; ++i)
-      if (i == I->getParent()->end() || i->mayHaveSideEffects())
+         i != UI; ++i) {
+      if (i == I->getParent()->end())
         return false;
+      if (!isGuaranteedToTransferExecutionToSuccessor(&*i))
+        return false;
+    }
 
     // Look through GEPs. A load from a GEP derived from NULL is still undefined
     if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Use))

diff  --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/while-loops.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/while-loops.ll
index cfa5a34da74b..a1dabc423171 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/while-loops.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/while-loops.ll
@@ -153,7 +153,7 @@ declare i32 @llvm.arm.mve.addv.predicated.v4i32.v4i1(<4 x i32>, i32, <4 x i1>)
 
 
 ; Long test that was spilling lr between t2LoopDec and End
-define dso_local i32 @b(i32* %c, i32 %d, i32 %e) "frame-pointer"="all" {
+define dso_local i32 @b(i32* %c, i32 %d, i32 %e, i32* %n) "frame-pointer"="all" {
 ; CHECK-LABEL: b:
 ; CHECK:       @ %bb.0: @ %entry
 ; CHECK-NEXT:    .save {r4, r5, r6, r7, lr}
@@ -162,79 +162,80 @@ define dso_local i32 @b(i32* %c, i32 %d, i32 %e) "frame-pointer"="all" {
 ; CHECK-NEXT:    add r7, sp, #12
 ; CHECK-NEXT:    .save {r8, r9, r10, r11}
 ; CHECK-NEXT:    push.w {r8, r9, r10, r11}
-; CHECK-NEXT:    .pad #8
-; CHECK-NEXT:    sub sp, #8
+; CHECK-NEXT:    .pad #12
+; CHECK-NEXT:    sub sp, #12
 ; CHECK-NEXT:    wls lr, r1, .LBB2_3
 ; CHECK-NEXT:  @ %bb.1: @ %while.body.preheader
-; CHECK-NEXT:    adds r1, r0, #4
-; CHECK-NEXT:    mvn r3, #1
-; CHECK-NEXT:    @ implicit-def: $r9
-; CHECK-NEXT:    @ implicit-def: $r10
+; CHECK-NEXT:    mov r4, r2
+; CHECK-NEXT:    adds r2, r3, #4
+; CHECK-NEXT:    add.w r9, r0, #4
+; CHECK-NEXT:    mvn r11, #1
 ; CHECK-NEXT:    @ implicit-def: $r6
-; CHECK-NEXT:    @ implicit-def: $r4
-; CHECK-NEXT:    str r2, [sp] @ 4-byte Spill
+; CHECK-NEXT:    @ implicit-def: $r12
+; CHECK-NEXT:    str r4, [sp] @ 4-byte Spill
 ; CHECK-NEXT:  .LBB2_2: @ %while.body
 ; CHECK-NEXT:    @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT:    str r1, [sp, #4] @ 4-byte Spill
-; CHECK-NEXT:    ldr r1, [sp, #4] @ 4-byte Reload
-; CHECK-NEXT:    ldr.w r8, [r10]
-; CHECK-NEXT:    ldr r1, [r1, #-4]
-; CHECK-NEXT:    mul r11, r8, r0
-; CHECK-NEXT:    adds r0, #4
-; CHECK-NEXT:    mul r1, r1, r9
-; CHECK-NEXT:    adds.w r12, r1, #-2147483648
+; CHECK-NEXT:    ldr r1, [r9, #-4]
+; CHECK-NEXT:    ldr.w r10, [r2]
+; CHECK-NEXT:    str r0, [sp, #4] @ 4-byte Spill
+; CHECK-NEXT:    muls r1, r3, r1
+; CHECK-NEXT:    adds.w r8, r1, #-2147483648
 ; CHECK-NEXT:    asr.w r5, r1, #31
-; CHECK-NEXT:    add.w r1, r11, #-2147483648
-; CHECK-NEXT:    adc r5, r5, #0
-; CHECK-NEXT:    asrl r12, r5, r1
-; CHECK-NEXT:    smull r2, r1, r8, r12
-; CHECK-NEXT:    lsll r2, r1, #30
-; CHECK-NEXT:    asrs r5, r1, #31
-; CHECK-NEXT:    mov r2, r1
-; CHECK-NEXT:    lsll r2, r5, r8
-; CHECK-NEXT:    lsll r2, r5, #30
-; CHECK-NEXT:    ldrd r2, r11, [r3]
+; CHECK-NEXT:    adc r1, r5, #0
+; CHECK-NEXT:    mul r5, r10, r0
+; CHECK-NEXT:    mov r0, r2
+; CHECK-NEXT:    ldr.w r2, [r11, #4]
+; CHECK-NEXT:    str r2, [sp, #8] @ 4-byte Spill
+; CHECK-NEXT:    ldr r2, [sp, #8] @ 4-byte Reload
+; CHECK-NEXT:    add.w r5, r5, #-2147483648
+; CHECK-NEXT:    asrl r8, r1, r5
+; CHECK-NEXT:    smull r4, r5, r10, r8
+; CHECK-NEXT:    lsll r4, r5, #30
 ; CHECK-NEXT:    asrs r1, r5, #31
-; CHECK-NEXT:    mov r12, r5
-; CHECK-NEXT:    asrs r5, r4, #31
-; CHECK-NEXT:    muls r2, r6, r2
-; CHECK-NEXT:    adds r2, #2
-; CHECK-NEXT:    lsll r12, r1, r2
-; CHECK-NEXT:    ldr r2, [sp, #4] @ 4-byte Reload
-; CHECK-NEXT:    add.w r1, r12, #-2147483648
-; CHECK-NEXT:    ldr r2, [r2]
-; CHECK-NEXT:    mul r2, r2, r9
-; CHECK-NEXT:    add.w r9, r9, #4
-; CHECK-NEXT:    adds r4, r4, r2
-; CHECK-NEXT:    adc.w r2, r5, r2, asr #31
-; CHECK-NEXT:    adds.w r5, r4, #-2147483648
-; CHECK-NEXT:    smull r6, r4, r11, r6
-; CHECK-NEXT:    adc r2, r2, #0
-; CHECK-NEXT:    asrs r5, r2, #31
-; CHECK-NEXT:    subs r6, r2, r6
+; CHECK-NEXT:    mov r4, r5
+; CHECK-NEXT:    lsll r4, r1, r10
+; CHECK-NEXT:    lsll r4, r1, #30
+; CHECK-NEXT:    ldr.w r4, [r11]
+; CHECK-NEXT:    asrs r5, r1, #31
+; CHECK-NEXT:    mov r8, r1
+; CHECK-NEXT:    muls r4, r6, r4
+; CHECK-NEXT:    adds r4, #2
+; CHECK-NEXT:    lsll r8, r5, r4
+; CHECK-NEXT:    ldr r4, [r9], #4
+; CHECK-NEXT:    asr.w r5, r12, #31
+; CHECK-NEXT:    add.w r8, r8, #-2147483648
+; CHECK-NEXT:    muls r4, r3, r4
+; CHECK-NEXT:    adds r3, #4
+; CHECK-NEXT:    adds.w r1, r12, r4
+; CHECK-NEXT:    adc.w r5, r5, r4, asr #31
+; CHECK-NEXT:    smull r6, r4, r2, r6
+; CHECK-NEXT:    adds.w r1, r1, #-2147483648
+; CHECK-NEXT:    adc r1, r5, #0
+; CHECK-NEXT:    mov r2, r0
+; CHECK-NEXT:    asrs r5, r1, #31
+; CHECK-NEXT:    subs r6, r1, r6
 ; CHECK-NEXT:    sbcs r5, r4
 ; CHECK-NEXT:    adds.w r6, r6, #-2147483648
 ; CHECK-NEXT:    adc r5, r5, #0
-; CHECK-NEXT:    asrl r6, r5, r1
-; CHECK-NEXT:    movs r1, #2
+; CHECK-NEXT:    asrl r6, r5, r8
 ; CHECK-NEXT:    lsrl r6, r5, #2
-; CHECK-NEXT:    str r6, [r1]
-; CHECK-NEXT:    ldr r1, [r3], #-4
-; CHECK-NEXT:    mls r1, r1, r8, r2
-; CHECK-NEXT:    adds.w r4, r1, #-2147483648
-; CHECK-NEXT:    asr.w r2, r1, #31
-; CHECK-NEXT:    adc r1, r2, #0
-; CHECK-NEXT:    ldr r2, [sp] @ 4-byte Reload
-; CHECK-NEXT:    lsrl r4, r1, #2
-; CHECK-NEXT:    rsbs r1, r4, #0
-; CHECK-NEXT:    str r1, [r10, #-4]
-; CHECK-NEXT:    add.w r10, r10, #4
-; CHECK-NEXT:    str r1, [r2]
-; CHECK-NEXT:    ldr r1, [sp, #4] @ 4-byte Reload
-; CHECK-NEXT:    adds r1, #4
+; CHECK-NEXT:    movs r5, #2
+; CHECK-NEXT:    str r6, [r5]
+; CHECK-NEXT:    ldr r5, [r11], #-4
+; CHECK-NEXT:    mls r1, r5, r10, r1
+; CHECK-NEXT:    adds.w r12, r1, #-2147483648
+; CHECK-NEXT:    asr.w r4, r1, #31
+; CHECK-NEXT:    adc r1, r4, #0
+; CHECK-NEXT:    ldrd r4, r0, [sp] @ 8-byte Folded Reload
+; CHECK-NEXT:    lsrl r12, r1, #2
+; CHECK-NEXT:    rsb.w r1, r12, #0
+; CHECK-NEXT:    adds r0, #4
+; CHECK-NEXT:    str r1, [r4]
+; CHECK-NEXT:    str r1, [r2, #-4]
+; CHECK-NEXT:    adds r2, #4
 ; CHECK-NEXT:    le lr, .LBB2_2
 ; CHECK-NEXT:  .LBB2_3: @ %while.end
-; CHECK-NEXT:    add sp, #8
+; CHECK-NEXT:    add sp, #12
 ; CHECK-NEXT:    pop.w {r8, r9, r10, r11}
 ; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}
 entry:
@@ -245,7 +246,7 @@ entry:
 while.body:                                       ; preds = %entry, %while.body
   %p.077 = phi i32* [ %incdec.ptr22, %while.body ], [ inttoptr (i32 2 to i32*), %entry ]
   %c.addr.076 = phi i32* [ %incdec.ptr1, %while.body ], [ %c, %entry ]
-  %n.075 = phi i32* [ %incdec.ptr43, %while.body ], [ undef, %entry ]
+  %n.075 = phi i32* [ %incdec.ptr43, %while.body ], [ %n, %entry ]
   %m.074 = phi i32 [ %conv35, %while.body ], [ undef, %entry ]
   %d.addr.073 = phi i32 [ %dec, %while.body ], [ %d, %entry ]
   %h.072 = phi i32 [ %conv41, %while.body ], [ undef, %entry ]

diff  --git a/llvm/test/Transforms/PhaseOrdering/d83507-knowledge-retention-bug.ll b/llvm/test/Transforms/PhaseOrdering/d83507-knowledge-retention-bug.ll
index 578f9f7e5b37..e5dd8dbd77ec 100644
--- a/llvm/test/Transforms/PhaseOrdering/d83507-knowledge-retention-bug.ll
+++ b/llvm/test/Transforms/PhaseOrdering/d83507-knowledge-retention-bug.ll
@@ -1,15 +1,15 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -O1                   -enable-knowledge-retention -S < %s  | FileCheck %s
-; RUN: opt -passes='default<O1>' -enable-knowledge-retention -S < %s  | FileCheck %s
+; RUN: opt -loop-rotate -instcombine -enable-knowledge-retention -S < %s  | FileCheck %s
+; RUN: opt -passes='loop(loop-rotate),instcombine' -enable-knowledge-retention -S < %s  | FileCheck %s
 
 %0 = type { %0* }
 
-define %0* @f1() local_unnamed_addr {
+define %0* @f1(%0* %i0) local_unnamed_addr {
 ; CHECK-LABEL: @f1(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:         br label [[BB3:%.*]]
 ; CHECK:       bb3:
-; CHECK-NEXT:    [[I1:%.*]] = phi %0* [ [[I5:%.*]], [[BB3]] ], [ undef, [[BB:%.*]] ]
+; CHECK-NEXT:    [[I1:%.*]] = phi %0* [ %i0, [[BB:%.*]] ], [ [[I5:%.*]], [[BB3]] ]
 ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(%0* [[I1]]) ]
 ; CHECK-NEXT:    [[I4:%.*]] = getelementptr inbounds [[TMP0:%.*]], %0* [[I1]], i64 0, i32 0
 ; CHECK-NEXT:    [[I5]] = load %0*, %0** [[I4]], align 8
@@ -22,7 +22,7 @@ bb:
   br label %bb1
 
 bb1:
-  %i = phi %0* [ undef, %bb ], [ %i5, %bb3 ]
+  %i = phi %0* [ %i0, %bb ], [ %i5, %bb3 ]
   %i2 = icmp eq %0* %i, null
   br i1 %i2, label %bb6, label %bb3
 

diff  --git a/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll b/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
index cdec29415bc6..0d6b941bb84f 100644
--- a/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
+++ b/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
@@ -84,6 +84,41 @@ bb2:
   ret void
 }
 
+declare void @llvm.assume(i1)
+declare i1 @llvm.type.test(i8*, metadata) nounwind readnone
+
+;; Same as the above test but make sure the unreachable control flow is still
+;; removed in the presence of a type test / assume sequence.
+
+define void @test5_type_test_assume(i1 %cond, i8* %ptr, [3 x i8*]* %vtable) {
+; CHECK-LABEL: @test5_type_test_assume(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[COND:%.*]], true
+; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
+; CHECK-NEXT:    [[VTABLE:%.*]] = bitcast [3 x i8*]* %vtable to i8*
+; CHECK-NEXT:    [[P:%.*]] = call i1 @llvm.type.test(i8* [[VTABLE]], metadata !"foo")
+; CHECK-NEXT:    tail call void @llvm.assume(i1 [[P]])
+; CHECK-NEXT:    store i8 2, i8* [[PTR:%.*]], align 8
+; CHECK-NEXT:    ret void
+;
+entry:
+  br i1 %cond, label %bb1, label %bb3
+
+bb3:
+  br label %bb2
+
+bb1:
+  br label %bb2
+
+bb2:
+  %ptr.2 = phi i8* [ %ptr, %bb3 ], [ null, %bb1 ]
+  %vtablei8 = bitcast [3 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"foo")
+  tail call void @llvm.assume(i1 %p)
+  store i8 2, i8* %ptr.2, align 8
+  ret void
+}
+
 define void @test5_no_null_opt(i1 %cond, i8* %ptr) #0 {
 ; CHECK-LABEL: @test5_no_null_opt(
 ; CHECK-NEXT:  entry:


        


More information about the llvm-commits mailing list