-; RUN: opt < %s -simplifycfg -S | FileCheck %s
-; XFAIL: *
+; RUN: opt -S -simplifycfg < %s | FileCheck -check-prefix=CHECK %s
+; RUN: opt -S -default-data-layout="p:32:32-p1:16:16" -simplifycfg < %s | FileCheck -check-prefix=CHECK -check-prefix=DL %s
declare void @foo1()
F: ; preds = %0
call void @foo2( )
ret void
-; CHECK: @test1
+; CHECK-LABEL: @test1(
; CHECK: switch i32 %V, label %F [
; CHECK: i32 17, label %T
; CHECK: i32 4, label %T
; CHECK: ]
}
+define void @test1_ptr(i32* %V) {
+ %C1 = icmp eq i32* %V, inttoptr (i32 4 to i32*)
+ %C2 = icmp eq i32* %V, inttoptr (i32 17 to i32*)
+ %CN = or i1 %C1, %C2 ; <i1> [#uses=1]
+ br i1 %CN, label %T, label %F
+T: ; preds = %0
+ call void @foo1( )
+ ret void
+F: ; preds = %0
+ call void @foo2( )
+ ret void
+; CHECK-LABEL: @test1_ptr(
+; DL: %magicptr = ptrtoint i32* %V to i32
+; DL: switch i32 %magicptr, label %F [
+; DL: i32 17, label %T
+; DL: i32 4, label %T
+; DL: ]
+}
+
+define void @test1_ptr_as1(i32 addrspace(1)* %V) {
+ %C1 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 4 to i32 addrspace(1)*)
+ %C2 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 17 to i32 addrspace(1)*)
+ %CN = or i1 %C1, %C2 ; <i1> [#uses=1]
+ br i1 %CN, label %T, label %F
+T: ; preds = %0
+ call void @foo1( )
+ ret void
+F: ; preds = %0
+ call void @foo2( )
+ ret void
+; CHECK-LABEL: @test1_ptr_as1(
+; DL: %magicptr = ptrtoint i32 addrspace(1)* %V to i16
+; DL: switch i16 %magicptr, label %F [
+; DL: i16 17, label %T
+; DL: i16 4, label %T
+; DL: ]
+}
+
define void @test2(i32 %V) {
%C1 = icmp ne i32 %V, 4 ; <i1> [#uses=1]
%C2 = icmp ne i32 %V, 17 ; <i1> [#uses=1]
F: ; preds = %0
call void @foo2( )
ret void
-; CHECK: @test2
+; CHECK-LABEL: @test2(
; CHECK: switch i32 %V, label %T [
; CHECK: i32 17, label %F
; CHECK: i32 4, label %F
call void @foo2( )
ret void
-; CHECK: @test3
+; CHECK-LABEL: @test3(
; CHECK: switch i32 %V, label %F [
; CHECK: i32 4, label %T
; CHECK: i32 17, label %T
%0 = phi i1 [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp8, %lor.rhs ]
%lor.ext = zext i1 %0 to i32
ret i32 %lor.ext
-
-; CHECK: @test4
+
+; CHECK-LABEL: @test4(
; CHECK: switch i8 %c, label %lor.rhs [
; CHECK: i8 62, label %lor.end
; CHECK: i8 34, label %lor.end
%0 = phi i1 [ true, %entry ], [ %V, %lor.rhs ], [ true, %entry ], [ true, %entry ]
%lor.ext = zext i1 %0 to i32
ret i32 %lor.ext
-; CHECK: @test5
+; CHECK-LABEL: @test5(
; CHECK: switch i8 %c, label %lor.rhs [
; CHECK: i8 62, label %lor.end
; CHECK: i8 34, label %lor.end
UnifiedReturnBlock: ; preds = %shortcirc_done.4, %shortcirc_next.4
%UnifiedRetVal = phi i1 [ %tmp.26, %shortcirc_next.4 ], [ true, %shortcirc_done.4 ] ; <i1> [#uses=1]
ret i1 %UnifiedRetVal
-
-; CHECK: @test6
-; CHECK: switch i32 %tmp.2.i, label %shortcirc_next.4 [
-; CHECK: i32 14, label %UnifiedReturnBlock
-; CHECK: i32 15, label %UnifiedReturnBlock
-; CHECK: i32 16, label %UnifiedReturnBlock
-; CHECK: i32 17, label %UnifiedReturnBlock
-; CHECK: i32 18, label %UnifiedReturnBlock
-; CHECK: i32 19, label %switch.edge
-; CHECK: ]
+
+; CHECK-LABEL: @test6(
+; CHECK: %tmp.2.i.off = add i32 %tmp.2.i, -14
+; CHECK: %switch = icmp ult i32 %tmp.2.i.off, 6
}
define void @test7(i8 zeroext %c, i32 %x) nounwind ssp noredzone {
if.end: ; preds = %entry
ret void
-
-; CHECK: @test7
+
+; CHECK-LABEL: @test7(
; CHECK: %cmp = icmp ult i32 %x, 32
; CHECK: br i1 %cmp, label %if.then, label %switch.early.test
; CHECK: switch.early.test:
if.end: ; preds = %entry
ret i32 0
-
-; CHECK: @test8
+
+; CHECK-LABEL: @test8(
; CHECK: switch.early.test:
; CHECK: switch i8 %c, label %if.end [
; CHECK: i8 99, label %if.then
%0 = phi i1 [ true, %lor.lhs.false36 ], [ true, %lor.lhs.false31 ], [ true, %lor.lhs.false26 ], [ true, %lor.lhs.false21 ], [ true, %lor.lhs.false16 ], [ true, %lor.lhs.false11 ], [ true, %lor.lhs.false6 ], [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp43, %lor.rhs ]
%conv46 = zext i1 %0 to i32
ret i32 %conv46
-
-; CHECK: @test9
-; HECK: %cmp = icmp ult i8 %c, 33
-; HECK: br i1 %cmp, label %lor.end, label %switch.early.test
-
-; HECK: switch.early.test:
-; HECK: switch i8 %c, label %lor.rhs [
-; HECK: i8 46, label %lor.end
-; HECK: i8 44, label %lor.end
-; HECK: i8 58, label %lor.end
-; HECK: i8 59, label %lor.end
-; HECK: i8 60, label %lor.end
-; HECK: i8 62, label %lor.end
-; HECK: i8 34, label %lor.end
-; HECK: i8 92, label %lor.end
-; HECK: i8 39, label %lor.end
-; HECK: ]
+
+; CHECK-LABEL: @test9(
+; CHECK: %cmp = icmp ult i8 %c, 33
+; CHECK: br i1 %cmp, label %lor.end, label %switch.early.test
+
+; CHECK: switch.early.test:
+; CHECK: switch i8 %c, label %lor.rhs [
+; CHECK: i8 92, label %lor.end
+; CHECK: i8 62, label %lor.end
+; CHECK: i8 60, label %lor.end
+; CHECK: i8 59, label %lor.end
+; CHECK: i8 58, label %lor.end
+; CHECK: i8 46, label %lor.end
+; CHECK: i8 44, label %lor.end
+; CHECK: i8 34, label %lor.end
+; CHECK: i8 39, label %lor.end
+; CHECK: ]
}
define i32 @test10(i32 %mode, i1 %Cond) {
F:
ret i32 324
-; CHECK: @test10
+; CHECK-LABEL: @test10(
; CHECK: br i1 %Cond, label %switch.early.test, label %F
; CHECK:switch.early.test:
; CHECK: switch i32 %mode, label %T [
%retval.0 = phi i32 [ 1, %if.then ], [ 0, %if.end ]
ret i32 %retval.0
-; CHECK: @test11
+; CHECK-LABEL: @test11(
; CHECK: switch i32 %bar, label %if.end [
; CHECK: i32 55, label %return
; CHECK: i32 53, label %return
malformed:
ret void
-; CHECK: @test12
+; CHECK-LABEL: @test12(
+
+}
+
+; test13 - handle switch formation with ult.
+define void @test13(i32 %x) nounwind ssp noredzone {
+entry:
+ %cmp = icmp ult i32 %x, 2
+ br i1 %cmp, label %if.then, label %lor.lhs.false3
+
+lor.lhs.false3: ; preds = %lor.lhs.false
+ %cmp5 = icmp eq i32 %x, 3
+ br i1 %cmp5, label %if.then, label %lor.lhs.false6
+
+lor.lhs.false6: ; preds = %lor.lhs.false3
+ %cmp8 = icmp eq i32 %x, 4
+ br i1 %cmp8, label %if.then, label %lor.lhs.false9
+
+lor.lhs.false9: ; preds = %lor.lhs.false6
+ %cmp11 = icmp eq i32 %x, 6
+ br i1 %cmp11, label %if.then, label %if.end
+
+if.then: ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
+ call void @foo1() noredzone
+ br label %if.end
+
+if.end: ; preds = %if.then, %lor.lhs.false9
+ ret void
+; CHECK-LABEL: @test13(
+; CHECK: switch i32 %x, label %if.end [
+; CHECK: i32 6, label %if.then
+; CHECK: i32 4, label %if.then
+; CHECK: i32 3, label %if.then
+; CHECK: i32 1, label %if.then
+; CHECK: i32 0, label %if.then
+; CHECK: ]
+}
+
+; test14 - handle switch formation with ult.
+define void @test14(i32 %x) nounwind ssp noredzone {
+entry:
+ %cmp = icmp ugt i32 %x, 2
+ br i1 %cmp, label %lor.lhs.false3, label %if.then
+
+lor.lhs.false3: ; preds = %lor.lhs.false
+ %cmp5 = icmp ne i32 %x, 3
+ br i1 %cmp5, label %lor.lhs.false6, label %if.then
+
+lor.lhs.false6: ; preds = %lor.lhs.false3
+ %cmp8 = icmp ne i32 %x, 4
+ br i1 %cmp8, label %lor.lhs.false9, label %if.then
+
+lor.lhs.false9: ; preds = %lor.lhs.false6
+ %cmp11 = icmp ne i32 %x, 6
+ br i1 %cmp11, label %if.end, label %if.then
+
+if.then: ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
+ call void @foo1() noredzone
+ br label %if.end
+
+if.end: ; preds = %if.then, %lor.lhs.false9
+ ret void
+; CHECK-LABEL: @test14(
+; CHECK: switch i32 %x, label %if.end [
+; CHECK: i32 6, label %if.then
+; CHECK: i32 4, label %if.then
+; CHECK: i32 3, label %if.then
+; CHECK: i32 1, label %if.then
+; CHECK: i32 0, label %if.then
+; CHECK: ]
+}
+
+; Don't crash on ginormous ranges.
+define void @test15(i128 %x) nounwind {
+ %cmp = icmp ugt i128 %x, 2
+ br i1 %cmp, label %if.end, label %lor.false
+
+lor.false:
+ %cmp2 = icmp ne i128 %x, 100000000000000000000
+ br i1 %cmp2, label %if.end, label %if.then
+
+if.then:
+ call void @foo1() noredzone
+ br label %if.end
+
+if.end:
+ ret void
+
+; CHECK-LABEL: @test15(
+; CHECK-NOT: switch
+; CHECK: ret void
+}
+
+; PR8675
+; rdar://5134905
+define zeroext i1 @test16(i32 %x) nounwind {
+entry:
+; CHECK-LABEL: @test16(
+; CHECK: %x.off = add i32 %x, -1
+; CHECK: %switch = icmp ult i32 %x.off, 3
+ %cmp.i = icmp eq i32 %x, 1
+ br i1 %cmp.i, label %lor.end, label %lor.lhs.false
+
+lor.lhs.false:
+ %cmp.i2 = icmp eq i32 %x, 2
+ br i1 %cmp.i2, label %lor.end, label %lor.rhs
+
+lor.rhs:
+ %cmp.i1 = icmp eq i32 %x, 3
+ br label %lor.end
+
+lor.end:
+ %0 = phi i1 [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp.i1, %lor.rhs ]
+ ret i1 %0
+}
+
+; Check that we don't turn an icmp into a switch where it's not useful.
+define void @test17(i32 %x, i32 %y) {
+ %cmp = icmp ult i32 %x, 3
+ %switch = icmp ult i32 %y, 2
+ %or.cond775 = or i1 %cmp, %switch
+ br i1 %or.cond775, label %lor.lhs.false8, label %return
+
+lor.lhs.false8:
+ tail call void @foo1()
+ ret void
-}
\ No newline at end of file
+return:
+ ret void
+
+; CHECK-LABEL: @test17(
+; CHECK-NOT: switch.early.test
+; CHECK-NOT: switch i32
+; CHECK: ret void
+}
+
+define void @test18(i32 %arg) {
+bb:
+ %tmp = and i32 %arg, -2
+ %tmp1 = icmp eq i32 %tmp, 8
+ %tmp2 = icmp eq i32 %arg, 10
+ %tmp3 = or i1 %tmp1, %tmp2
+ %tmp4 = icmp eq i32 %arg, 11
+ %tmp5 = or i1 %tmp3, %tmp4
+ %tmp6 = icmp eq i32 %arg, 12
+ %tmp7 = or i1 %tmp5, %tmp6
+ br i1 %tmp7, label %bb19, label %bb8
+
+bb8: ; preds = %bb
+ %tmp9 = add i32 %arg, -13
+ %tmp10 = icmp ult i32 %tmp9, 2
+ %tmp11 = icmp eq i32 %arg, 16
+ %tmp12 = or i1 %tmp10, %tmp11
+ %tmp13 = icmp eq i32 %arg, 17
+ %tmp14 = or i1 %tmp12, %tmp13
+ %tmp15 = icmp eq i32 %arg, 18
+ %tmp16 = or i1 %tmp14, %tmp15
+ %tmp17 = icmp eq i32 %arg, 15
+ %tmp18 = or i1 %tmp16, %tmp17
+ br i1 %tmp18, label %bb19, label %bb20
+
+bb19: ; preds = %bb8, %bb
+ tail call void @foo1()
+ br label %bb20
+
+bb20: ; preds = %bb19, %bb8
+ ret void
+
+; CHECK-LABEL: @test18(
+; CHECK: %arg.off = add i32 %arg, -8
+; CHECK: icmp ult i32 %arg.off, 11
+}