Files
clang-p2996/llvm/test/Transforms/LoopUnswitch/2011-11-18-SimpleSwitch.ll
Whitney Tsang 2a814cd9e1 Ensure SplitEdge to return the new block between the two given blocks
This PR implements the function splitBasicBlockBefore to address an
issue
that occurred during SplitEdge(BB, Succ, ...), inside splitBlockBefore.
The issue occurs in SplitEdge when the Succ has a single predecessor
and the edge between the BB and Succ is not critical. This produces
the result ‘BB->Succ->New’. The new function splitBasicBlockBefore
was added to splitBlockBefore to handle the issue and now produces
the correct result ‘BB->New->Succ’.

Below is an example of splitting the block bb1 at its first instruction.

/// Original IR
bb0:
	br bb1
bb1:
        %0 = mul i32 1, 2
	br bb2
bb2:
/// IR after splitEdge(bb0, bb1) using splitBasicBlock
bb0:
	br bb1
bb1:
	br bb1.split
bb1.split:
        %0 = mul i32 1, 2
	br bb2
bb2:
/// IR after splitEdge(bb0, bb1) using splitBasicBlockBefore
bb0:
	br bb1.split
bb1.split
	br bb1
bb1:
        %0 = mul i32 1, 2
	br bb2
bb2:

Differential Revision: https://reviews.llvm.org/D92200
2020-12-18 17:37:17 +00:00

96 lines
3.5 KiB
LLVM

; REQUIRES: asserts
; RUN: opt -loop-unswitch -enable-new-pm=0 -disable-output -stats -info-output-file - < %s | FileCheck --check-prefix=STATS %s
; RUN: opt -S -loop-unswitch -enable-new-pm=0 -verify-loop-info -verify-dom-info < %s | FileCheck %s
; RUN: opt -S -loop-unswitch -enable-new-pm=0 -verify-loop-info -verify-dom-info -enable-mssa-loop-dependency=true -verify-memoryssa < %s | FileCheck %s
; STATS: 2 loop-unswitch - Number of switches unswitched
; CHECK: %1 = icmp eq i32 %c, 1
; CHECK-NEXT: br i1 %1, label %.split.us, label %..split_crit_edge
; CHECK: ..split_crit_edge: ; preds = %0
; CHECK-NEXT: br label %.split
; CHECK: .split.us: ; preds = %0
; CHECK-NEXT: br label %loop_begin.us
; CHECK: loop_begin.us: ; preds = %loop_begin.backedge.us, %.split.us
; CHECK-NEXT: %var_val.us = load i32, i32* %var
; CHECK-NEXT: switch i32 1, label %default.us-lcssa.us [
; CHECK-NEXT: i32 1, label %inc.us
; CHECK: inc.us: ; preds = %loop_begin.us
; CHECK-NEXT: call void @incf() [[NOR_NUW:#[0-9]+]]
; CHECK-NEXT: br label %loop_begin.backedge.us
; CHECK: .split: ; preds = %..split_crit_edge
; CHECK-NEXT: %2 = icmp eq i32 %c, 2
; CHECK-NEXT: br i1 %2, label %.split.split.us, label %.split..split.split_crit_edge
; CHECK: .split..split.split_crit_edge: ; preds = %.split
; CHECK-NEXT: br label %.split.split
; CHECK: .split.split.us: ; preds = %.split
; CHECK-NEXT: br label %loop_begin.us1
; CHECK: loop_begin.us1: ; preds = %loop_begin.backedge.us5, %.split.split.us
; CHECK-NEXT: %var_val.us2 = load i32, i32* %var
; CHECK-NEXT: switch i32 2, label %default.us-lcssa.us-lcssa.us [
; CHECK-NEXT: i32 1, label %inc.split.us
; CHECK-NEXT: i32 2, label %dec.us3
; CHECK-NEXT: ]
; CHECK: dec.us3: ; preds = %loop_begin.us1
; CHECK-NEXT: call void @decf() [[NOR_NUW]]
; CHECK-NEXT: br label %loop_begin.backedge.us5
; CHECK: .split.split: ; preds = %.split..split.split_crit_edge
; CHECK-NEXT: br label %loop_begin
; CHECK: loop_begin: ; preds = %loop_begin.backedge, %.split.split
; CHECK-NEXT: %var_val = load i32, i32* %var
; CHECK-NEXT: switch i32 %c, label %default.us-lcssa.us-lcssa [
; CHECK-NEXT: i32 1, label %inc.split
; CHECK-NEXT: i32 2, label %dec.split
; CHECK-NEXT: ]
; CHECK: inc.split: ; preds = %loop_begin
; CHECK-NEXT: br i1 true, label %us-unreachable.us-lcssa, label %inc
; CHECK: dec.split: ; preds = %loop_begin
; CHECK-NEXT: br i1 true, label %us-unreachable6, label %dec
define i32 @test(i32* %var) {
%mem = alloca i32
store i32 2, i32* %mem
%c = load i32, i32* %mem
br label %loop_begin
loop_begin:
%var_val = load i32, i32* %var
switch i32 %c, label %default [
i32 1, label %inc
i32 2, label %dec
]
inc:
call void @incf() noreturn nounwind
br label %loop_begin
dec:
call void @decf() noreturn nounwind
br label %loop_begin
default:
br label %loop_exit
loop_exit:
ret i32 0
}
declare void @incf() noreturn
declare void @decf() noreturn
; CHECK: attributes #0 = { noreturn }
; CHECK: attributes [[NOR_NUW]] = { noreturn nounwind }