mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
c1e656184f
Sometimes SimplifyCFG may decide to perform jump threading. In order to do it, it follows the following algorithm: 1. Checks if the block is small enough for threading; 2. If yes, inserts a PR Phi relying that the next iteration will remove it by performing jump threading; 3. The next iteration checks the block again and performs the threading. This logic has a corner case: inserting the PR Phi increases block's size by 1. If the block size at first check was max possible, one more Phi will exceed this size, and we will neither perform threading nor remove the created Phi node. As result, we will end up with worse IR than before. This patch fixes this situation by excluding Phis from block size computation. Excluding Phis from size computation for threading also makes sense by itself because in case of threadign all those Phis will be removed. Differential Revision: https://reviews.llvm.org/D81835 Reviewed By: asbirlea, nikic
168 lines
7.0 KiB
LLVM
168 lines
7.0 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -simplifycfg -simplifycfg-max-small-block-size=10 -S < %s | FileCheck %s
|
|
; RUN: opt -passes=simplify-cfg -simplifycfg-max-small-block-size=10 -S < %s | FileCheck %s
|
|
|
|
target datalayout = "e-p:64:64-p5:32:32-A5"
|
|
|
|
declare void @llvm.assume(i1)
|
|
|
|
define void @test_01(i1 %c, i64* align 1 %ptr) local_unnamed_addr #0 {
|
|
; CHECK-LABEL: @test_01(
|
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE2_CRITEDGE:%.*]], label [[FALSE1:%.*]]
|
|
; CHECK: false1:
|
|
; CHECK-NEXT: store volatile i64 1, i64* [[PTR:%.*]], align 4
|
|
; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i64* [[PTR]] to i64
|
|
; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 7
|
|
; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
|
|
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]])
|
|
; CHECK-NEXT: store volatile i64 0, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 3, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: true2.critedge:
|
|
; CHECK-NEXT: [[PTRINT_C:%.*]] = ptrtoint i64* [[PTR]] to i64
|
|
; CHECK-NEXT: [[MASKEDPTR_C:%.*]] = and i64 [[PTRINT_C]], 7
|
|
; CHECK-NEXT: [[MASKCOND_C:%.*]] = icmp eq i64 [[MASKEDPTR_C]], 0
|
|
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND_C]])
|
|
; CHECK-NEXT: store volatile i64 0, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 2, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
br i1 %c, label %true1, label %false1
|
|
|
|
true1: ; preds = %false1, %0
|
|
%ptrint = ptrtoint i64* %ptr to i64
|
|
%maskedptr = and i64 %ptrint, 7
|
|
%maskcond = icmp eq i64 %maskedptr, 0
|
|
tail call void @llvm.assume(i1 %maskcond)
|
|
store volatile i64 0, i64* %ptr, align 8
|
|
br i1 %c, label %true2, label %false2
|
|
|
|
false1: ; preds = %0
|
|
store volatile i64 1, i64* %ptr, align 4
|
|
br label %true1
|
|
|
|
true2: ; preds = %true1
|
|
store volatile i64 2, i64* %ptr, align 8
|
|
ret void
|
|
|
|
false2: ; preds = %true1
|
|
store volatile i64 3, i64* %ptr, align 8
|
|
ret void
|
|
}
|
|
|
|
; Corner case: the block has max possible size for which we still do PRE.
|
|
define void @test_02(i1 %c, i64* align 1 %ptr) local_unnamed_addr #0 {
|
|
; CHECK-LABEL: @test_02(
|
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE2_CRITEDGE:%.*]], label [[FALSE1:%.*]]
|
|
; CHECK: false1:
|
|
; CHECK-NEXT: store volatile i64 1, i64* [[PTR:%.*]], align 4
|
|
; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i64* [[PTR]] to i64
|
|
; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 7
|
|
; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
|
|
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]])
|
|
; CHECK-NEXT: store volatile i64 0, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 3, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: true2.critedge:
|
|
; CHECK-NEXT: [[PTRINT_C:%.*]] = ptrtoint i64* [[PTR]] to i64
|
|
; CHECK-NEXT: [[MASKEDPTR_C:%.*]] = and i64 [[PTRINT_C]], 7
|
|
; CHECK-NEXT: [[MASKCOND_C:%.*]] = icmp eq i64 [[MASKEDPTR_C]], 0
|
|
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND_C]])
|
|
; CHECK-NEXT: store volatile i64 0, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 2, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
br i1 %c, label %true1, label %false1
|
|
|
|
true1: ; preds = %false1, %0
|
|
%ptrint = ptrtoint i64* %ptr to i64
|
|
%maskedptr = and i64 %ptrint, 7
|
|
%maskcond = icmp eq i64 %maskedptr, 0
|
|
tail call void @llvm.assume(i1 %maskcond)
|
|
store volatile i64 0, i64* %ptr, align 8
|
|
store volatile i64 -1, i64* %ptr, align 8
|
|
store volatile i64 -1, i64* %ptr, align 8
|
|
store volatile i64 -1, i64* %ptr, align 8
|
|
store volatile i64 -1, i64* %ptr, align 8
|
|
store volatile i64 -1, i64* %ptr, align 8
|
|
br i1 %c, label %true2, label %false2
|
|
|
|
false1: ; preds = %0
|
|
store volatile i64 1, i64* %ptr, align 4
|
|
br label %true1
|
|
|
|
true2: ; preds = %true1
|
|
store volatile i64 2, i64* %ptr, align 8
|
|
ret void
|
|
|
|
false2: ; preds = %true1
|
|
store volatile i64 3, i64* %ptr, align 8
|
|
ret void
|
|
}
|
|
|
|
; This block is too huge for PRE.
|
|
define void @test_03(i1 %c, i64* align 1 %ptr) local_unnamed_addr #0 {
|
|
; CHECK-LABEL: @test_03(
|
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE1:%.*]], label [[FALSE1:%.*]]
|
|
; CHECK: true1:
|
|
; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i64* [[PTR:%.*]] to i64
|
|
; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 7
|
|
; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
|
|
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]])
|
|
; CHECK-NEXT: store volatile i64 0, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: br i1 [[C]], label [[TRUE2:%.*]], label [[FALSE2:%.*]]
|
|
; CHECK: false1:
|
|
; CHECK-NEXT: store volatile i64 1, i64* [[PTR]], align 4
|
|
; CHECK-NEXT: br label [[TRUE1]]
|
|
; CHECK: true2:
|
|
; CHECK-NEXT: store volatile i64 2, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: false2:
|
|
; CHECK-NEXT: store volatile i64 3, i64* [[PTR]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
br i1 %c, label %true1, label %false1
|
|
|
|
true1: ; preds = %false1, %0
|
|
%ptrint = ptrtoint i64* %ptr to i64
|
|
%maskedptr = and i64 %ptrint, 7
|
|
%maskcond = icmp eq i64 %maskedptr, 0
|
|
tail call void @llvm.assume(i1 %maskcond)
|
|
store volatile i64 0, i64* %ptr, align 8
|
|
store volatile i64 -1, i64* %ptr, align 8
|
|
store volatile i64 -1, i64* %ptr, align 8
|
|
store volatile i64 -1, i64* %ptr, align 8
|
|
store volatile i64 -1, i64* %ptr, align 8
|
|
store volatile i64 -1, i64* %ptr, align 8
|
|
store volatile i64 -1, i64* %ptr, align 8
|
|
br i1 %c, label %true2, label %false2
|
|
|
|
false1: ; preds = %0
|
|
store volatile i64 1, i64* %ptr, align 4
|
|
br label %true1
|
|
|
|
true2: ; preds = %true1
|
|
store volatile i64 2, i64* %ptr, align 8
|
|
ret void
|
|
|
|
false2: ; preds = %true1
|
|
store volatile i64 3, i64* %ptr, align 8
|
|
ret void
|
|
}
|