diff --git a/clang/test/CodeGenObjC/exceptions.m b/clang/test/CodeGenObjC/exceptions.m --- a/clang/test/CodeGenObjC/exceptions.m +++ b/clang/test/CodeGenObjC/exceptions.m @@ -25,11 +25,12 @@ // CHECK-NEXT: icmp // CHECK-NEXT: br i1 @try { - // CHECK: call void asm sideeffect "", "=*m" // CHECK: call void asm sideeffect "", "*m" // CHECK-NEXT: call void @foo() foo(); // CHECK: call void @objc_exception_try_exit + // CHECK: try.handler: + // CHECK: call void asm sideeffect "", "=*m" } @finally { break; @@ -53,12 +54,6 @@ // CHECK-NEXT: [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0 // CHECK-NEXT: br i1 [[CAUGHT]] @try { - // Landing pad. Note that we elide the re-enter. - // CHECK: call void asm sideeffect "", "=*m,=*m"(i32* nonnull elementtype(i32) [[X]] - // CHECK-NEXT: call i8* @objc_exception_extract - // CHECK-NEXT: [[T1:%.*]] = load i32, i32* [[X]] - // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1 - // CHECK: store i32 6, i32* [[X]] x++; // CHECK-NEXT: call void asm sideeffect "", "*m,*m"(i32* nonnull elementtype(i32) [[X]] @@ -67,6 +62,12 @@ // CHECK-NEXT: [[T:%.*]] = load i32, i32* [[X]] foo(); } @catch (id) { + // Landing pad. Note that we elide the re-enter. + // CHECK: call void asm sideeffect "", "=*m,=*m"(i32* nonnull elementtype(i32) [[X]] + // CHECK-NEXT: call i8* @objc_exception_extract + // CHECK-NEXT: [[T1:%.*]] = load i32, i32* [[X]] + // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1 + x--; } diff --git a/clang/test/CodeGenObjCXX/exceptions-legacy.mm b/clang/test/CodeGenObjCXX/exceptions-legacy.mm --- a/clang/test/CodeGenObjCXX/exceptions-legacy.mm +++ b/clang/test/CodeGenObjCXX/exceptions-legacy.mm @@ -63,20 +63,19 @@ // Body. // CHECK: invoke void @_Z3foov() -// Catch handler. Reload of 'failed' address is unnecessary. -// CHECK: [[T0:%.*]] = load i8*, i8** -// CHECK-NEXT: store i8 1, i8* [[T0]], -// CHECK-NEXT: br label - // Leave the @try. // CHECK: call void @objc_exception_try_exit([[BUF_T]]* nonnull [[BUF]]) // CHECK-NEXT: br label // CHECK: ret void - // Real EH cleanup. // CHECK: [[T0:%.*]] = landingpad // CHECK-NEXT: cleanup // CHECK-NEXT: call void @objc_exception_try_exit([[BUF_T]]* nonnull [[BUF]]) // CHECK-NEXT: resume +// Catch handler. Reload of 'failed' address is unnecessary. +// CHECK: [[T0:%.*]] = load i8*, i8** +// CHECK-NEXT: store i8 1, i8* [[T0]], +// CHECK-NEXT: br label + diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -2975,8 +2975,10 @@ return true; } -static ConstantInt *getKnownValueOnEdge(Value *V, BasicBlock *From, - BasicBlock *To) { +static ConstantInt * +getKnownValueOnEdge(Value *V, BasicBlock *From, BasicBlock *To, + SmallDenseMap, + ConstantInt *> &Visited) { // Don't look past the block defining the value, we might get the value from // a previous loop iteration. auto *I = dyn_cast(V); @@ -2990,7 +2992,23 @@ return BI->getSuccessor(0) == To ? ConstantInt::getTrue(BI->getContext()) : ConstantInt::getFalse(BI->getContext()); - return nullptr; + // Limit the amount of blocks we inspect. + if (Visited.size() >= 8) + return nullptr; + + auto Pair = Visited.try_emplace({From, To}, nullptr); + if (!Pair.second) + return Pair.first->second; + + // Check whether the known value is the same for all predecessors. + ConstantInt *Common = nullptr; + for (BasicBlock *Pred : predecessors(From)) { + ConstantInt *C = getKnownValueOnEdge(V, Pred, From, Visited); + if (!C || (Common && Common != C)) + return nullptr; + Common = C; + } + return Visited[{From, To}] = Common; } /// If we have a conditional branch on something for which we know the constant @@ -3015,8 +3033,9 @@ if (auto *CB = dyn_cast(U)) KnownValues.insert({PN->getIncomingBlock(U), CB}); } else { + SmallDenseMap, ConstantInt *> Visited; for (BasicBlock *Pred : predecessors(BB)) { - if (ConstantInt *CB = getKnownValueOnEdge(Cond, Pred, BB)) + if (ConstantInt *CB = getKnownValueOnEdge(Cond, Pred, BB, Visited)) KnownValues.insert({Pred, CB}); } } diff --git a/llvm/test/CodeGen/AArch64/arm64-andCmpBrToTBZ.ll b/llvm/test/CodeGen/AArch64/arm64-andCmpBrToTBZ.ll --- a/llvm/test/CodeGen/AArch64/arm64-andCmpBrToTBZ.ll +++ b/llvm/test/CodeGen/AArch64/arm64-andCmpBrToTBZ.ll @@ -36,7 +36,7 @@ if.end5: ; preds = %_ZNK7WebCore4Node10hasTagNameERKNS_13QualifiedNameE.exit, %lor.rhs.i.i.i ; CHECK: %if.end5 ; CHECK: tbz - br i1 %tobool.i.i.i, label %if.end12, label %land.rhs.i19, !prof !1 + br i1 %IsEditable, label %if.end12, label %land.rhs.i19, !prof !1 land.rhs.i19: ; preds = %if.end5 %cmp.i.i.i18 = icmp eq i8* %str6, %str7 diff --git a/llvm/test/Transforms/GVNSink/sink-common-code.ll b/llvm/test/Transforms/GVNSink/sink-common-code.ll --- a/llvm/test/Transforms/GVNSink/sink-common-code.ll +++ b/llvm/test/Transforms/GVNSink/sink-common-code.ll @@ -604,7 +604,7 @@ declare void @g() ; CHECK-LABEL: test_pr30292 -; CHECK: phi i32 [ 0, %entry ], [ %add1, %succ ], [ %add2, %two ] +; CHECK: phi i32 [ 0, %entry ], [ %add1, %succ ] define zeroext i1 @test_pr30244(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks) { diff --git a/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll b/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll --- a/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll @@ -885,9 +885,9 @@ ; CHECK: two: ; CHECK-NEXT: call void @g() ; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[A]], 1 -; CHECK-NEXT: br label [[SUCC]] +; CHECK-NEXT: br label [[TWO:%.*]] ; CHECK: succ: -; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD1]], [[SUCC]] ], [ [[ADD2]], [[TWO:%.*]] ] +; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD1]], [[SUCC]] ] ; CHECK-NEXT: br i1 [[COND:%.*]], label [[TWO]], label [[SUCC]] ; entry: diff --git a/llvm/test/Transforms/SimplifyCFG/jump-threading.ll b/llvm/test/Transforms/SimplifyCFG/jump-threading.ll --- a/llvm/test/Transforms/SimplifyCFG/jump-threading.ll +++ b/llvm/test/Transforms/SimplifyCFG/jump-threading.ll @@ -144,16 +144,10 @@ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] ; CHECK: if: ; CHECK-NEXT: call void @foo() -; CHECK-NEXT: br label [[JOIN:%.*]] -; CHECK: else: -; CHECK-NEXT: call void @bar() -; CHECK-NEXT: br label [[JOIN]] -; CHECK: join: -; CHECK-NEXT: br i1 [[C]], label [[IF2:%.*]], label [[ELSE2:%.*]] -; CHECK: if2: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[JOIN2:%.*]] -; CHECK: else2: +; CHECK: else: +; CHECK-NEXT: call void @bar() ; CHECK-NEXT: call void @bar() ; CHECK-NEXT: br label [[JOIN2]] ; CHECK: join2: @@ -189,17 +183,12 @@ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] ; CHECK: if: ; CHECK-NEXT: call void @foo() -; CHECK-NEXT: br label [[JOIN:%.*]] -; CHECK: else: -; CHECK-NEXT: call void @bar() -; CHECK-NEXT: br label [[JOIN]] -; CHECK: join: ; CHECK-NEXT: call void @use.i1(i1 [[C]]) -; CHECK-NEXT: br i1 [[C]], label [[IF2:%.*]], label [[ELSE2:%.*]] -; CHECK: if2: ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[JOIN2:%.*]] -; CHECK: else2: +; CHECK: else: +; CHECK-NEXT: call void @bar() +; CHECK-NEXT: call void @use.i1(i1 [[C]]) ; CHECK-NEXT: call void @bar() ; CHECK-NEXT: br label [[JOIN2]] ; CHECK: join2: @@ -236,17 +225,11 @@ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] ; CHECK: if: ; CHECK-NEXT: call void @foo() -; CHECK-NEXT: br label [[JOIN:%.*]] -; CHECK: else: -; CHECK-NEXT: call void @bar() -; CHECK-NEXT: br label [[JOIN]] -; CHECK: join: -; CHECK-NEXT: br i1 [[C]], label [[IF2:%.*]], label [[ELSE2:%.*]] -; CHECK: if2: ; CHECK-NEXT: call void @use.i1(i1 [[C]]) ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br label [[JOIN2:%.*]] -; CHECK: else2: +; CHECK: else: +; CHECK-NEXT: call void @bar() ; CHECK-NEXT: call void @use.i1(i1 [[C]]) ; CHECK-NEXT: call void @bar() ; CHECK-NEXT: br label [[JOIN2]] diff --git a/llvm/test/Transforms/SimplifyCFG/wc-widen-block.ll b/llvm/test/Transforms/SimplifyCFG/wc-widen-block.ll --- a/llvm/test/Transforms/SimplifyCFG/wc-widen-block.ll +++ b/llvm/test/Transforms/SimplifyCFG/wc-widen-block.ll @@ -269,17 +269,18 @@ define i32 @neg_loop(i1 %cond_0, i1 %cond_1) { ; CHECK-LABEL: @neg_loop( ; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[GUARDED:%.*]] +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[LOOP:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] +; CHECK: loop.critedge: +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: br label [[LOOP]] ; CHECK: loop: ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[LOOP_CRITEDGE:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: [[DEOPTRET:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTRET]] -; CHECK: guarded: -; CHECK-NEXT: call void @unknown() -; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[LOOP:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: [[DEOPTRET2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTRET2]]