[llvm] 9cd68bf - [SCCP] Add additional tests for structs, conditional prop and widening.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 18 06:08:36 PDT 2020


Author: Florian Hahn
Date: 2020-04-18T14:07:56+01:00
New Revision: 9cd68bfa0e49f755a0cc90b27025fa2e48083050

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

LOG: [SCCP] Add additional tests for structs, conditional prop and widening.

This patch adds a few additional test cases with cases subsequent patches
will improve on.

Added: 
    llvm/test/Transforms/SCCP/constant-range-struct.ll

Modified: 
    llvm/test/Transforms/SCCP/conditions-ranges.ll
    llvm/test/Transforms/SCCP/widening.ll

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/SCCP/conditions-ranges.ll b/llvm/test/Transforms/SCCP/conditions-ranges.ll
index f23bdfabc698..400c49e337df 100644
--- a/llvm/test/Transforms/SCCP/conditions-ranges.ll
+++ b/llvm/test/Transforms/SCCP/conditions-ranges.ll
@@ -1059,3 +1059,156 @@ false:
   call void @use(i1 %c.5)
   ret void
 }
+
+define void @f19_conditions_chained_and_nested_and(i32 %a, i32 %b) {
+; CHECK-LABEL: @f19_conditions_chained_and_nested_and(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LT_A:%.*]] = icmp ult i32 [[A:%.*]], 100
+; CHECK-NEXT:    [[LT_B:%.*]] = icmp ult i32 [[B:%.*]], 1000
+; CHECK-NEXT:    [[BC:%.*]] = and i1 [[LT_A]], [[LT_B]]
+; CHECK-NEXT:    br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]]
+; CHECK:       true:
+; CHECK-NEXT:    [[GT_A:%.*]] = icmp ugt i32 [[A]], 30
+; CHECK-NEXT:    [[GT_B:%.*]] = icmp ugt i32 [[B]], 300
+; CHECK-NEXT:    [[BC_2:%.*]] = and i1 [[GT_A]], [[GT_B]]
+; CHECK-NEXT:    br i1 [[BC_2]], label [[TRUE_2:%.*]], label [[FALSE]]
+; CHECK:       true.2:
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    [[C_1:%.*]] = icmp eq i32 [[A]], 31
+; CHECK-NEXT:    call void @use(i1 [[C_1]])
+; CHECK-NEXT:    [[C_2:%.*]] = icmp ugt i32 [[A]], 31
+; CHECK-NEXT:    call void @use(i1 [[C_2]])
+; CHECK-NEXT:    [[C_3:%.*]] = icmp ugt i32 [[A]], 50
+; CHECK-NEXT:    call void @use(i1 [[C_3]])
+; CHECK-NEXT:    [[C_4:%.*]] = icmp eq i32 [[B]], 301
+; CHECK-NEXT:    call void @use(i1 [[C_4]])
+; CHECK-NEXT:    [[C_5:%.*]] = icmp ugt i32 [[B]], 301
+; CHECK-NEXT:    call void @use(i1 [[C_5]])
+; CHECK-NEXT:    [[C_6:%.*]] = icmp ugt i32 [[B]], 500
+; CHECK-NEXT:    call void @use(i1 [[C_6]])
+; CHECK-NEXT:    ret void
+; CHECK:       false:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %lt.a = icmp ult i32 %a, 100
+  %lt.b = icmp ult i32 %b, 1000
+  %bc = and i1 %lt.a, %lt.b
+  br i1 %bc, label %true, label %false
+
+true:
+  %gt.a = icmp ugt i32 %a, 30
+  %gt.b = icmp ugt i32 %b, 300
+  %bc.2 = and i1 %gt.a, %gt.b
+  br i1 %bc.2, label %true.2, label %false
+
+true.2:
+  ; Conditions below are false.
+  %f.1 = icmp eq i32 %a, 0
+  call void @use(i1 %f.1)
+  %f.2 = icmp eq i32 %a, 20
+  call void @use(i1 %f.2)
+  %f.3 = icmp ugt i32 %a, 100
+  call void @use(i1 %f.3)
+  %f.4 = icmp eq i32 %b, 0
+  call void @use(i1 %f.4)
+  %f.5 = icmp eq i32 %b, 300
+  call void @use(i1 %f.5)
+  %f.6 = icmp ugt i32 %b, 1000
+  call void @use(i1 %f.6)
+
+
+  ; Conditions below are true.
+  %t.1 = icmp ult i32 %a, 100
+  call void @use(i1 %t.1)
+  %t.2 = icmp ne i32 %a, 20
+  call void @use(i1 %t.2)
+  %t.3 = icmp ult i32 %b, 1000
+  call void @use(i1 %t.3)
+  %t.4 = icmp ne i32 %b, 300
+  call void @use(i1 %t.4)
+
+
+  ; Conditions below cannot be simplified.
+  %c.1 = icmp eq i32 %a, 31
+  call void @use(i1 %c.1)
+  %c.2 = icmp ugt i32 %a, 31
+  call void @use(i1 %c.2)
+  %c.3 = icmp ugt i32 %a, 50
+  call void @use(i1 %c.3)
+  %c.4 = icmp eq i32 %b, 301
+  call void @use(i1 %c.4)
+  %c.5 = icmp ugt i32 %b, 301
+  call void @use(i1 %c.5)
+  %c.6 = icmp ugt i32 %b, 500
+  call void @use(i1 %c.6)
+
+  ret void
+
+false:
+  ret void
+}
+
+declare i64 @get_i64()
+
+declare i1 @cond()
+
+define void @f20_ne_0_nuked_by_and(i32 %arg) local_unnamed_addr #0 {
+; CHECK-LABEL: @f20_ne_0_nuked_by_and(
+; CHECK-NEXT:  bb11:
+; CHECK-NEXT:    br label [[BB122:%.*]]
+; CHECK:       bb122:
+; CHECK-NEXT:    [[TMP123:%.*]] = phi i32 [ 256, [[BB11:%.*]] ], [ [[TMP136:%.*]], [[BB135:%.*]] ]
+; CHECK-NEXT:    [[TMP127:%.*]] = call i64 @get_i64()
+; CHECK-NEXT:    [[TMP128:%.*]] = trunc i64 [[TMP127]] to i32
+; CHECK-NEXT:    [[TMP131:%.*]] = icmp ne i32 [[TMP128]], 0
+; CHECK-NEXT:    [[TMP132:%.*]] = icmp sgt i32 [[TMP123]], [[TMP128]]
+; CHECK-NEXT:    [[TMP133:%.*]] = and i1 [[TMP131]], [[TMP132]]
+; CHECK-NEXT:    br i1 [[TMP133]], label [[BB134:%.*]], label [[BB135]]
+; CHECK:       bb134:
+; CHECK-NEXT:    br label [[BB135]]
+; CHECK:       bb135:
+; CHECK-NEXT:    [[TMP136]] = phi i32 [ [[TMP123]], [[BB122]] ], [ [[TMP128]], [[BB134]] ]
+; CHECK-NEXT:    [[BC:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[BC]], label [[BB139:%.*]], label [[BB122]]
+; CHECK:       bb139:
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    ret void
+;
+bb11:                                             ; preds = %bb1
+  br label %bb122
+
+bb122:                                            ; preds = %bb135, %bb120
+  %tmp123 = phi i32 [ 256, %bb11 ], [ %tmp136, %bb135 ]
+  %tmp127 = call i64 @get_i64()
+  %tmp128 = trunc i64 %tmp127 to i32
+  %tmp131 = icmp ne i32 %tmp128, 0
+  %tmp132 = icmp sgt i32 %tmp123, %tmp128
+  %tmp133 = and i1 %tmp131, %tmp132
+  br i1 %tmp133, label %bb134, label %bb135
+
+bb134:                                            ; preds = %bb122
+  br label %bb135
+
+bb135:                                            ; preds = %bb134, %bb122
+  %tmp136 = phi i32 [ %tmp123, %bb122 ], [ %tmp128, %bb134 ]
+  %bc = call i1 @cond()
+  br i1 %bc, label %bb139, label %bb122
+
+bb139:                                            ; preds = %bb135
+  %tmp140 = icmp eq i32 %tmp136, 0
+  call void @use(i1 %tmp140)
+  ret void
+
+bb142:                                            ; preds = %bb139
+  ret void
+}

diff  --git a/llvm/test/Transforms/SCCP/constant-range-struct.ll b/llvm/test/Transforms/SCCP/constant-range-struct.ll
new file mode 100644
index 000000000000..d3c5e5513b9e
--- /dev/null
+++ b/llvm/test/Transforms/SCCP/constant-range-struct.ll
@@ -0,0 +1,164 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt %s -ipsccp -S | FileCheck %s
+
+declare i1 @cond()
+declare void @use(i1)
+
+define internal {i64, i64} @struct1() {
+; CHECK-LABEL: @struct1(
+; CHECK-NEXT:    [[C:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]]
+; CHECK:       true:
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       false:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[R:%.*]] = phi { i64, i64 } [ { i64 20, i64 200 }, [[TRUE]] ], [ { i64 30, i64 300 }, [[FALSE]] ]
+; CHECK-NEXT:    ret { i64, i64 } [[R]]
+;
+  %c = call i1 @cond()
+  br i1 %c, label %true, label %false
+
+true:
+  %s.1 = insertvalue {i64, i64} undef, i64 20, 0
+  %s.2 = insertvalue {i64, i64} %s.1, i64 200, 1
+  br label %exit
+
+false:
+  %s.3 = insertvalue {i64, i64} undef, i64 30, 0
+  %s.4 = insertvalue {i64, i64} %s.3, i64 300, 1
+  br label %exit
+
+exit:
+  %r = phi {i64, i64} [ %s.2, %true], [ %s.4, %false ]
+  ret {i64, i64} %r
+}
+
+define void @struct1_caller() {
+; CHECK-LABEL: @struct1_caller(
+; CHECK-NEXT:    [[S:%.*]] = call { i64, i64 } @struct1()
+; CHECK-NEXT:    [[V1:%.*]] = extractvalue { i64, i64 } [[S]], 0
+; CHECK-NEXT:    [[V2:%.*]] = extractvalue { i64, i64 } [[S]], 1
+; CHECK-NEXT:    [[T_1:%.*]] = icmp ne i64 [[V1]], 10
+; CHECK-NEXT:    call void @use(i1 [[T_1]])
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult i64 [[V1]], 100
+; CHECK-NEXT:    call void @use(i1 [[T_2]])
+; CHECK-NEXT:    [[T_3:%.*]] = icmp ne i64 [[V2]], 0
+; CHECK-NEXT:    call void @use(i1 [[T_3]])
+; CHECK-NEXT:    [[T_4:%.*]] = icmp ult i64 [[V2]], 301
+; CHECK-NEXT:    call void @use(i1 [[T_4]])
+; CHECK-NEXT:    ret void
+;
+  %s = call {i64, i64} @struct1()
+  %v1 = extractvalue {i64, i64} %s, 0
+  %v2 = extractvalue {i64, i64} %s, 1
+
+  %t.1 = icmp ne i64 %v1, 10
+  call void @use(i1 %t.1)
+  %t.2 = icmp ult i64 %v1, 100
+  call void @use(i1 %t.2)
+  %t.3 = icmp ne i64 %v2, 0
+  call void @use(i1 %t.3)
+  %t.4 = icmp ult i64 %v2, 301
+  call void @use(i1 %t.4)
+
+  ret void
+}
+
+define internal {i64, i64} @struct2() {
+; CHECK-LABEL: @struct2(
+; CHECK-NEXT:    [[C:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]]
+; CHECK:       true:
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       false:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[V1:%.*]] = phi i64 [ 20, [[TRUE]] ], [ 30, [[FALSE]] ]
+; CHECK-NEXT:    [[V2:%.*]] = phi i64 [ 200, [[TRUE]] ], [ 300, [[FALSE]] ]
+; CHECK-NEXT:    [[S_1:%.*]] = insertvalue { i64, i64 } undef, i64 [[V1]], 0
+; CHECK-NEXT:    [[S_2:%.*]] = insertvalue { i64, i64 } [[S_1]], i64 [[V2]], 1
+; CHECK-NEXT:    ret { i64, i64 } [[S_2]]
+;
+  %c = call i1 @cond()
+  br i1 %c, label %true, label %false
+
+true:
+  br label %exit
+
+false:
+  br label %exit
+
+exit:
+  %v1 = phi i64 [ 20, %true ], [ 30, %false ]
+  %v2 = phi i64 [ 200, %true ], [ 300, %false ]
+  %s.1 = insertvalue {i64, i64} undef, i64 %v1, 0
+  %s.2 = insertvalue {i64, i64} %s.1, i64 %v2, 1
+  ret {i64, i64} %s.2
+}
+
+define void @struct2_caller() {
+; CHECK-LABEL: @struct2_caller(
+; CHECK-NEXT:    [[S:%.*]] = call { i64, i64 } @struct2()
+; CHECK-NEXT:    [[V1:%.*]] = extractvalue { i64, i64 } [[S]], 0
+; CHECK-NEXT:    [[V2:%.*]] = extractvalue { i64, i64 } [[S]], 1
+; CHECK-NEXT:    [[T_1:%.*]] = icmp ne i64 [[V1]], 10
+; CHECK-NEXT:    call void @use(i1 [[T_1]])
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult i64 [[V1]], 100
+; CHECK-NEXT:    call void @use(i1 [[T_2]])
+; CHECK-NEXT:    [[T_3:%.*]] = icmp ne i64 [[V2]], 0
+; CHECK-NEXT:    call void @use(i1 [[T_3]])
+; CHECK-NEXT:    [[T_4:%.*]] = icmp ult i64 [[V2]], 301
+; CHECK-NEXT:    call void @use(i1 [[T_4]])
+; CHECK-NEXT:    [[F_1:%.*]] = icmp eq i64 [[V1]], 10
+; CHECK-NEXT:    call void @use(i1 [[F_1]])
+; CHECK-NEXT:    [[F_2:%.*]] = icmp ult i64 [[V1]], 19
+; CHECK-NEXT:    call void @use(i1 [[F_2]])
+; CHECK-NEXT:    [[F_3:%.*]] = icmp eq i64 [[V2]], 50
+; CHECK-NEXT:    call void @use(i1 [[F_3]])
+; CHECK-NEXT:    [[F_4:%.*]] = icmp ugt i64 [[V2]], 301
+; CHECK-NEXT:    call void @use(i1 [[F_4]])
+; CHECK-NEXT:    [[C_1:%.*]] = icmp eq i64 [[V1]], 25
+; CHECK-NEXT:    call void @use(i1 [[C_1]])
+; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i64 [[V1]], 25
+; CHECK-NEXT:    call void @use(i1 [[C_2]])
+; CHECK-NEXT:    [[C_3:%.*]] = icmp eq i64 [[V2]], 250
+; CHECK-NEXT:    call void @use(i1 [[C_3]])
+; CHECK-NEXT:    [[C_4:%.*]] = icmp ugt i64 [[V2]], 250
+; CHECK-NEXT:    call void @use(i1 [[C_4]])
+; CHECK-NEXT:    ret void
+;
+  %s = call {i64, i64} @struct2()
+  %v1 = extractvalue {i64, i64} %s, 0
+  %v2 = extractvalue {i64, i64} %s, 1
+
+  %t.1 = icmp ne i64 %v1, 10
+  call void @use(i1 %t.1)
+  %t.2 = icmp ult i64 %v1, 100
+  call void @use(i1 %t.2)
+  %t.3 = icmp ne i64 %v2, 0
+  call void @use(i1 %t.3)
+  %t.4 = icmp ult i64 %v2, 301
+  call void @use(i1 %t.4)
+
+  %f.1 = icmp eq i64 %v1, 10
+  call void @use(i1 %f.1)
+  %f.2 = icmp ult i64 %v1, 19
+  call void @use(i1 %f.2)
+  %f.3 = icmp eq i64 %v2, 50
+  call void @use(i1 %f.3)
+  %f.4 = icmp ugt i64 %v2, 301
+  call void @use(i1 %f.4)
+
+  %c.1 = icmp eq i64 %v1, 25
+  call void @use(i1 %c.1)
+  %c.2 = icmp ult i64 %v1, 25
+  call void @use(i1 %c.2)
+  %c.3 = icmp eq i64 %v2, 250
+  call void @use(i1 %c.3)
+  %c.4 = icmp ugt i64 %v2, 250
+  call void @use(i1 %c.4)
+
+
+  ret void
+}

diff  --git a/llvm/test/Transforms/SCCP/widening.ll b/llvm/test/Transforms/SCCP/widening.ll
index b475e75ed362..8e4f3b520596 100644
--- a/llvm/test/Transforms/SCCP/widening.ll
+++ b/llvm/test/Transforms/SCCP/widening.ll
@@ -442,3 +442,440 @@ loop.body:
 exit:
   ret void
 }
+
+; In the function below, the condition %c.1 results in a range [7, 6), which
+; can be used as a widening bound. It does not fully contain the range we get
+; from combining it with the information from %tmp12.
+define void @foo(i64* %arg) {
+; SCCP-LABEL: @foo(
+; SCCP-NEXT:  bb:
+; SCCP-NEXT:    [[TMP:%.*]] = zext i8 undef to i32
+; SCCP-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i64, i64* [[ARG:%.*]], i32 0
+; SCCP-NEXT:    [[TMP2:%.*]] = load i64, i64* [[TMP1]], align 8
+; SCCP-NEXT:    switch i32 [[TMP]], label [[BB20:%.*]] [
+; SCCP-NEXT:    i32 1, label [[BB3:%.*]]
+; SCCP-NEXT:    i32 2, label [[BB4:%.*]]
+; SCCP-NEXT:    i32 4, label [[BB19:%.*]]
+; SCCP-NEXT:    ]
+; SCCP:       bb3:
+; SCCP-NEXT:    unreachable
+; SCCP:       bb4:
+; SCCP-NEXT:    [[TMP5:%.*]] = add i64 [[TMP2]], 3
+; SCCP-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 3
+; SCCP-NEXT:    [[TMP7:%.*]] = sub i64 3, [[TMP6]]
+; SCCP-NEXT:    [[TMP8:%.*]] = shl i64 [[TMP7]], 1
+; SCCP-NEXT:    [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32
+; SCCP-NEXT:    [[TMP10:%.*]] = sext i32 [[TMP9]] to i64
+; SCCP-NEXT:    br label [[BB11:%.*]]
+; SCCP:       bb11:
+; SCCP-NEXT:    [[TMP12:%.*]] = phi i64 [ [[TMP10]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ]
+; SCCP-NEXT:    br label [[BB13:%.*]]
+; SCCP:       bb13:
+; SCCP-NEXT:    [[C_1:%.*]] = icmp eq i64 [[TMP12]], 6
+; SCCP-NEXT:    br i1 [[C_1]], label [[BB15:%.*]], label [[BB16:%.*]]
+; SCCP:       bb15:
+; SCCP-NEXT:    unreachable
+; SCCP:       bb16:
+; SCCP-NEXT:    [[TMP17]] = add i64 [[TMP12]], 2
+; SCCP-NEXT:    br label [[BB18]]
+; SCCP:       bb18:
+; SCCP-NEXT:    br label [[BB11]]
+; SCCP:       bb19:
+; SCCP-NEXT:    unreachable
+; SCCP:       bb20:
+; SCCP-NEXT:    ret void
+;
+; IPSCCP-LABEL: @foo(
+; IPSCCP-NEXT:  bb:
+; IPSCCP-NEXT:    [[TMP:%.*]] = zext i8 undef to i32
+; IPSCCP-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i64, i64* [[ARG:%.*]], i32 0
+; IPSCCP-NEXT:    [[TMP2:%.*]] = load i64, i64* [[TMP1]], align 8
+; IPSCCP-NEXT:    switch i32 [[TMP]], label [[BB20:%.*]] [
+; IPSCCP-NEXT:    i32 1, label [[BB3:%.*]]
+; IPSCCP-NEXT:    i32 2, label [[BB4:%.*]]
+; IPSCCP-NEXT:    i32 4, label [[BB19:%.*]]
+; IPSCCP-NEXT:    ]
+; IPSCCP:       bb3:
+; IPSCCP-NEXT:    unreachable
+; IPSCCP:       bb4:
+; IPSCCP-NEXT:    [[TMP5:%.*]] = add i64 [[TMP2]], 3
+; IPSCCP-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 3
+; IPSCCP-NEXT:    [[TMP7:%.*]] = sub i64 3, [[TMP6]]
+; IPSCCP-NEXT:    [[TMP8:%.*]] = shl i64 [[TMP7]], 1
+; IPSCCP-NEXT:    [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32
+; IPSCCP-NEXT:    [[TMP10:%.*]] = sext i32 [[TMP9]] to i64
+; IPSCCP-NEXT:    br label [[BB11:%.*]]
+; IPSCCP:       bb11:
+; IPSCCP-NEXT:    [[TMP12:%.*]] = phi i64 [ [[TMP10]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ]
+; IPSCCP-NEXT:    br label [[BB13:%.*]]
+; IPSCCP:       bb13:
+; IPSCCP-NEXT:    [[C_1:%.*]] = icmp eq i64 [[TMP12]], 6
+; IPSCCP-NEXT:    br i1 [[C_1]], label [[BB15:%.*]], label [[BB16:%.*]]
+; IPSCCP:       bb15:
+; IPSCCP-NEXT:    unreachable
+; IPSCCP:       bb16:
+; IPSCCP-NEXT:    [[TMP17]] = add i64 [[TMP12]], 2
+; IPSCCP-NEXT:    br label [[BB18]]
+; IPSCCP:       bb18:
+; IPSCCP-NEXT:    br label [[BB11]]
+; IPSCCP:       bb19:
+; IPSCCP-NEXT:    unreachable
+; IPSCCP:       bb20:
+; IPSCCP-NEXT:    ret void
+;
+bb:
+  %tmp = zext i8 undef to i32
+  %tmp1 = getelementptr inbounds i64, i64* %arg, i32 0
+  %tmp2 = load i64, i64* %tmp1, align 8
+  switch i32 %tmp, label %bb20 [
+  i32 1, label %bb3
+  i32 2, label %bb4
+  i32 4, label %bb19
+  ]
+
+bb3:                                              ; preds = %bb
+  unreachable
+
+bb4:                                              ; preds = %bb
+  %tmp5 = add i64 %tmp2, 3
+  %tmp6 = and i64 %tmp5, 3
+  %tmp7 = sub i64 3, %tmp6
+  %tmp8 = shl i64 %tmp7, 1
+  %tmp9 = trunc i64 %tmp8 to i32
+  %tmp10 = sext i32 %tmp9 to i64
+  br label %bb11
+
+bb11:                                             ; preds = %bb18, %bb4
+  %tmp12 = phi i64 [ %tmp10, %bb4 ], [ %tmp17, %bb18 ]
+  br label %bb13
+
+bb13:                                             ; preds = %bb11
+  %c.1 = icmp eq i64 %tmp12, 6
+  br i1 %c.1, label %bb15, label %bb16
+
+bb15:                                             ; preds = %bb13
+  unreachable
+
+bb16:                                             ; preds = %bb13
+  %tmp17 = add i64 %tmp12, 2
+  br label %bb18
+
+bb18:                                             ; preds = %bb16
+  br label %bb11
+
+bb19:                                             ; preds = %bb
+  unreachable
+
+bb20:                                             ; preds = %bb
+  ret void
+}
+
+; The functions below check that widening with an upper bound does correctly
+; return whether the range changed. Make sure we do not eliminate %c.2.
+
+%struct.baz.1 = type { i32, i32, i8*, i8* }
+%struct.blam.2 = type <{ %struct.baz.1, i32, [4 x i8] }>
+
+ at global.11 = linkonce_odr global [4 x i8] zeroinitializer, align 1
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #1
+
+define linkonce_odr dereferenceable(1) i8* @spam(%struct.baz.1* %arg, i32 %arg1) align 2 {
+; SCCP-LABEL: @spam(
+; SCCP-NEXT:  bb:
+; SCCP-NEXT:    [[TMP:%.*]] = getelementptr inbounds [[STRUCT_BAZ_1:%.*]], %struct.baz.1* [[ARG:%.*]], i32 0, i32 3
+; SCCP-NEXT:    [[TMP2:%.*]] = load i8*, i8** [[TMP]], align 8
+; SCCP-NEXT:    [[TMP3:%.*]] = sext i32 [[ARG1:%.*]] to i64
+; SCCP-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i8, i8* [[TMP2]], i64 [[TMP3]]
+; SCCP-NEXT:    ret i8* [[TMP4]]
+;
+; IPSCCP-LABEL: @spam(
+; IPSCCP-NEXT:  bb:
+; IPSCCP-NEXT:    [[TMP:%.*]] = getelementptr inbounds [[STRUCT_BAZ_1:%.*]], %struct.baz.1* [[ARG:%.*]], i32 0, i32 3
+; IPSCCP-NEXT:    [[TMP2:%.*]] = load i8*, i8** [[TMP]], align 8
+; IPSCCP-NEXT:    [[TMP3:%.*]] = sext i32 [[ARG1:%.*]] to i64
+; IPSCCP-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i8, i8* [[TMP2]], i64 [[TMP3]]
+; IPSCCP-NEXT:    ret i8* [[TMP4]]
+;
+bb:
+  %tmp = getelementptr inbounds %struct.baz.1, %struct.baz.1* %arg, i32 0, i32 3
+  %tmp2 = load i8*, i8** %tmp, align 8
+  %tmp3 = sext i32 %arg1 to i64
+  %tmp4 = getelementptr inbounds i8, i8* %tmp2, i64 %tmp3
+  ret i8* %tmp4
+}
+
+define i8* @wobble(%struct.blam.2* %arg, i32 %arg1) align 2 {
+; SCCP-LABEL: @wobble(
+; SCCP-NEXT:  bb:
+; SCCP-NEXT:    [[TMP:%.*]] = lshr i32 [[ARG1:%.*]], 16
+; SCCP-NEXT:    [[TMP2:%.*]] = xor i32 [[TMP]], [[ARG1]]
+; SCCP-NEXT:    [[TMP3:%.*]] = and i32 [[TMP2]], 65535
+; SCCP-NEXT:    [[TMP4:%.*]] = mul i32 [[ARG1]], 8
+; SCCP-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2:%.*]], %struct.blam.2* [[ARG:%.*]], i32 0, i32 1
+; SCCP-NEXT:    [[TMP6:%.*]] = load i32, i32* [[TMP5]], align 8
+; SCCP-NEXT:    [[TMP7:%.*]] = and i32 [[TMP4]], [[TMP6]]
+; SCCP-NEXT:    br label [[BB8:%.*]]
+; SCCP:       bb8:
+; SCCP-NEXT:    [[TMP9:%.*]] = phi i8* [ undef, [[BB:%.*]] ], [ [[TMP17:%.*]], [[BB29:%.*]] ]
+; SCCP-NEXT:    [[TMP10:%.*]] = phi i16* [ undef, [[BB]] ], [ [[TMP18:%.*]], [[BB29]] ]
+; SCCP-NEXT:    [[TMP11:%.*]] = phi i32 [ 0, [[BB]] ], [ [[TMP30:%.*]], [[BB29]] ]
+; SCCP-NEXT:    [[C_1:%.*]] = icmp slt i32 [[TMP11]], 8
+; SCCP-NEXT:    br i1 [[C_1]], label [[BB13:%.*]], label [[BB31:%.*]]
+; SCCP:       bb13:
+; SCCP-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0
+; SCCP-NEXT:    [[TMP15:%.*]] = add i32 [[TMP7]], [[TMP11]]
+; SCCP-NEXT:    [[TMP16:%.*]] = mul i32 [[TMP15]], 4
+; SCCP-NEXT:    [[TMP17]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP14]], i32 [[TMP16]])
+; SCCP-NEXT:    [[TMP18]] = bitcast i8* [[TMP17]] to i16*
+; SCCP-NEXT:    [[TMP19:%.*]] = getelementptr inbounds i8, i8* [[TMP17]], i64 2
+; SCCP-NEXT:    [[TMP20:%.*]] = load i8, i8* [[TMP19]], align 1
+; SCCP-NEXT:    [[TMP21:%.*]] = zext i8 [[TMP20]] to i32
+; SCCP-NEXT:    [[TMP22:%.*]] = icmp eq i32 [[TMP21]], 0
+; SCCP-NEXT:    br i1 [[TMP22]], label [[BB23:%.*]], label [[BB25:%.*]]
+; SCCP:       bb23:
+; SCCP-NEXT:    [[TMP24:%.*]] = trunc i32 [[TMP3]] to i16
+; SCCP-NEXT:    store i16 [[TMP24]], i16* [[TMP18]], align 2
+; SCCP-NEXT:    br label [[BB31]]
+; SCCP:       bb25:
+; SCCP-NEXT:    [[TMP26:%.*]] = load i16, i16* [[TMP18]], align 2
+; SCCP-NEXT:    [[TMP27:%.*]] = zext i16 [[TMP26]] to i32
+; SCCP-NEXT:    [[TMP28:%.*]] = icmp eq i32 [[TMP27]], [[TMP3]]
+; SCCP-NEXT:    br i1 [[TMP28]], label [[BB31]], label [[BB29]]
+; SCCP:       bb29:
+; SCCP-NEXT:    [[TMP30]] = add nsw i32 [[TMP11]], 1
+; SCCP-NEXT:    br label [[BB8]]
+; SCCP:       bb31:
+; SCCP-NEXT:    [[TMP32:%.*]] = phi i8* [ [[TMP17]], [[BB23]] ], [ [[TMP17]], [[BB25]] ], [ [[TMP9]], [[BB8]] ]
+; SCCP-NEXT:    [[TMP33:%.*]] = phi i16* [ [[TMP18]], [[BB23]] ], [ [[TMP18]], [[BB25]] ], [ [[TMP10]], [[BB8]] ]
+; SCCP-NEXT:    [[TMP34:%.*]] = icmp eq i32 [[TMP11]], 0
+; SCCP-NEXT:    br i1 [[TMP34]], label [[BB35:%.*]], label [[BB37:%.*]]
+; SCCP:       bb35:
+; SCCP-NEXT:    [[TMP36:%.*]] = getelementptr inbounds i8, i8* [[TMP32]], i64 1
+; SCCP-NEXT:    br label [[BB66:%.*]]
+; SCCP:       bb37:
+; SCCP-NEXT:    [[C_2:%.*]] = icmp eq i32 [[TMP11]], 8
+; SCCP-NEXT:    br i1 [[C_2]], label [[BB39:%.*]], label [[BB58:%.*]]
+; SCCP:       bb39:
+; SCCP-NEXT:    [[TMP40:%.*]] = add nsw i32 [[TMP11]], -1
+; SCCP-NEXT:    [[TMP41:%.*]] = trunc i32 [[TMP3]] to i16
+; SCCP-NEXT:    store i16 [[TMP41]], i16* bitcast ([4 x i8]* @global.11 to i16*), align 1
+; SCCP-NEXT:    [[TMP42:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0
+; SCCP-NEXT:    [[TMP43:%.*]] = add i32 [[TMP7]], [[TMP40]]
+; SCCP-NEXT:    [[TMP44:%.*]] = mul i32 [[TMP43]], 4
+; SCCP-NEXT:    [[TMP45:%.*]] = add i32 [[TMP44]], 2
+; SCCP-NEXT:    [[TMP46:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP42]], i32 [[TMP45]])
+; SCCP-NEXT:    [[TMP47:%.*]] = load i8, i8* [[TMP46]], align 1
+; SCCP-NEXT:    [[TMP48:%.*]] = zext i8 [[TMP47]] to i32
+; SCCP-NEXT:    [[TMP49:%.*]] = sub i32 [[TMP43]], 1
+; SCCP-NEXT:    [[TMP50:%.*]] = mul i32 [[TMP49]], 4
+; SCCP-NEXT:    [[TMP51:%.*]] = add i32 [[TMP50]], 2
+; SCCP-NEXT:    [[TMP52:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP42]], i32 [[TMP51]])
+; SCCP-NEXT:    [[TMP53:%.*]] = load i8, i8* [[TMP52]], align 1
+; SCCP-NEXT:    [[TMP54:%.*]] = zext i8 [[TMP53]] to i32
+; SCCP-NEXT:    [[TMP55:%.*]] = icmp sgt i32 [[TMP48]], [[TMP54]]
+; SCCP-NEXT:    br i1 [[TMP55]], label [[BB56:%.*]], label [[BB60:%.*]]
+; SCCP:       bb56:
+; SCCP-NEXT:    [[TMP57:%.*]] = add nsw i32 [[TMP40]], -1
+; SCCP-NEXT:    br label [[BB60]]
+; SCCP:       bb58:
+; SCCP-NEXT:    [[TMP59:%.*]] = bitcast i16* [[TMP33]] to i8*
+; SCCP-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 getelementptr inbounds ([4 x i8], [4 x i8]* @global.11, i64 0, i64 0), i8* align 2 [[TMP59]], i64 4, i1 false)
+; SCCP-NEXT:    br label [[BB60]]
+; SCCP:       bb60:
+; SCCP-NEXT:    [[TMP61:%.*]] = phi i32 [ [[TMP57]], [[BB56]] ], [ [[TMP40]], [[BB39]] ], [ [[TMP11]], [[BB58]] ]
+; SCCP-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0
+; SCCP-NEXT:    [[TMP63:%.*]] = add i32 [[TMP7]], 1
+; SCCP-NEXT:    [[TMP64:%.*]] = mul i32 [[TMP63]], 4
+; SCCP-NEXT:    [[TMP65:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP62]], i32 [[TMP64]])
+; SCCP-NEXT:    br label [[BB66]]
+; SCCP:       bb66:
+; SCCP-NEXT:    [[TMP67:%.*]] = phi i8* [ [[TMP36]], [[BB35]] ], [ null, [[BB60]] ]
+; SCCP-NEXT:    ret i8* [[TMP67]]
+;
+; IPSCCP-LABEL: @wobble(
+; IPSCCP-NEXT:  bb:
+; IPSCCP-NEXT:    [[TMP:%.*]] = lshr i32 [[ARG1:%.*]], 16
+; IPSCCP-NEXT:    [[TMP2:%.*]] = xor i32 [[TMP]], [[ARG1]]
+; IPSCCP-NEXT:    [[TMP3:%.*]] = and i32 [[TMP2]], 65535
+; IPSCCP-NEXT:    [[TMP4:%.*]] = mul i32 [[ARG1]], 8
+; IPSCCP-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2:%.*]], %struct.blam.2* [[ARG:%.*]], i32 0, i32 1
+; IPSCCP-NEXT:    [[TMP6:%.*]] = load i32, i32* [[TMP5]], align 8
+; IPSCCP-NEXT:    [[TMP7:%.*]] = and i32 [[TMP4]], [[TMP6]]
+; IPSCCP-NEXT:    br label [[BB8:%.*]]
+; IPSCCP:       bb8:
+; IPSCCP-NEXT:    [[TMP9:%.*]] = phi i8* [ undef, [[BB:%.*]] ], [ [[TMP17:%.*]], [[BB29:%.*]] ]
+; IPSCCP-NEXT:    [[TMP10:%.*]] = phi i16* [ undef, [[BB]] ], [ [[TMP18:%.*]], [[BB29]] ]
+; IPSCCP-NEXT:    [[TMP11:%.*]] = phi i32 [ 0, [[BB]] ], [ [[TMP30:%.*]], [[BB29]] ]
+; IPSCCP-NEXT:    [[C_1:%.*]] = icmp slt i32 [[TMP11]], 8
+; IPSCCP-NEXT:    br i1 [[C_1]], label [[BB13:%.*]], label [[BB31:%.*]]
+; IPSCCP:       bb13:
+; IPSCCP-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0
+; IPSCCP-NEXT:    [[TMP15:%.*]] = add i32 [[TMP7]], [[TMP11]]
+; IPSCCP-NEXT:    [[TMP16:%.*]] = mul i32 [[TMP15]], 4
+; IPSCCP-NEXT:    [[TMP17]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP14]], i32 [[TMP16]])
+; IPSCCP-NEXT:    [[TMP18]] = bitcast i8* [[TMP17]] to i16*
+; IPSCCP-NEXT:    [[TMP19:%.*]] = getelementptr inbounds i8, i8* [[TMP17]], i64 2
+; IPSCCP-NEXT:    [[TMP20:%.*]] = load i8, i8* [[TMP19]], align 1
+; IPSCCP-NEXT:    [[TMP21:%.*]] = zext i8 [[TMP20]] to i32
+; IPSCCP-NEXT:    [[TMP22:%.*]] = icmp eq i32 [[TMP21]], 0
+; IPSCCP-NEXT:    br i1 [[TMP22]], label [[BB23:%.*]], label [[BB25:%.*]]
+; IPSCCP:       bb23:
+; IPSCCP-NEXT:    [[TMP24:%.*]] = trunc i32 [[TMP3]] to i16
+; IPSCCP-NEXT:    store i16 [[TMP24]], i16* [[TMP18]], align 2
+; IPSCCP-NEXT:    br label [[BB31]]
+; IPSCCP:       bb25:
+; IPSCCP-NEXT:    [[TMP26:%.*]] = load i16, i16* [[TMP18]], align 2
+; IPSCCP-NEXT:    [[TMP27:%.*]] = zext i16 [[TMP26]] to i32
+; IPSCCP-NEXT:    [[TMP28:%.*]] = icmp eq i32 [[TMP27]], [[TMP3]]
+; IPSCCP-NEXT:    br i1 [[TMP28]], label [[BB31]], label [[BB29]]
+; IPSCCP:       bb29:
+; IPSCCP-NEXT:    [[TMP30]] = add nsw i32 [[TMP11]], 1
+; IPSCCP-NEXT:    br label [[BB8]]
+; IPSCCP:       bb31:
+; IPSCCP-NEXT:    [[TMP32:%.*]] = phi i8* [ [[TMP17]], [[BB23]] ], [ [[TMP17]], [[BB25]] ], [ [[TMP9]], [[BB8]] ]
+; IPSCCP-NEXT:    [[TMP33:%.*]] = phi i16* [ [[TMP18]], [[BB23]] ], [ [[TMP18]], [[BB25]] ], [ [[TMP10]], [[BB8]] ]
+; IPSCCP-NEXT:    [[TMP34:%.*]] = icmp eq i32 [[TMP11]], 0
+; IPSCCP-NEXT:    br i1 [[TMP34]], label [[BB35:%.*]], label [[BB37:%.*]]
+; IPSCCP:       bb35:
+; IPSCCP-NEXT:    [[TMP36:%.*]] = getelementptr inbounds i8, i8* [[TMP32]], i64 1
+; IPSCCP-NEXT:    br label [[BB66:%.*]]
+; IPSCCP:       bb37:
+; IPSCCP-NEXT:    [[C_2:%.*]] = icmp eq i32 [[TMP11]], 8
+; IPSCCP-NEXT:    br i1 [[C_2]], label [[BB39:%.*]], label [[BB58:%.*]]
+; IPSCCP:       bb39:
+; IPSCCP-NEXT:    [[TMP40:%.*]] = add nsw i32 [[TMP11]], -1
+; IPSCCP-NEXT:    [[TMP41:%.*]] = trunc i32 [[TMP3]] to i16
+; IPSCCP-NEXT:    store i16 [[TMP41]], i16* bitcast ([4 x i8]* @global.11 to i16*), align 1
+; IPSCCP-NEXT:    [[TMP42:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0
+; IPSCCP-NEXT:    [[TMP43:%.*]] = add i32 [[TMP7]], [[TMP40]]
+; IPSCCP-NEXT:    [[TMP44:%.*]] = mul i32 [[TMP43]], 4
+; IPSCCP-NEXT:    [[TMP45:%.*]] = add i32 [[TMP44]], 2
+; IPSCCP-NEXT:    [[TMP46:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP42]], i32 [[TMP45]])
+; IPSCCP-NEXT:    [[TMP47:%.*]] = load i8, i8* [[TMP46]], align 1
+; IPSCCP-NEXT:    [[TMP48:%.*]] = zext i8 [[TMP47]] to i32
+; IPSCCP-NEXT:    [[TMP49:%.*]] = sub i32 [[TMP43]], 1
+; IPSCCP-NEXT:    [[TMP50:%.*]] = mul i32 [[TMP49]], 4
+; IPSCCP-NEXT:    [[TMP51:%.*]] = add i32 [[TMP50]], 2
+; IPSCCP-NEXT:    [[TMP52:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP42]], i32 [[TMP51]])
+; IPSCCP-NEXT:    [[TMP53:%.*]] = load i8, i8* [[TMP52]], align 1
+; IPSCCP-NEXT:    [[TMP54:%.*]] = zext i8 [[TMP53]] to i32
+; IPSCCP-NEXT:    [[TMP55:%.*]] = icmp sgt i32 [[TMP48]], [[TMP54]]
+; IPSCCP-NEXT:    br i1 [[TMP55]], label [[BB56:%.*]], label [[BB60:%.*]]
+; IPSCCP:       bb56:
+; IPSCCP-NEXT:    [[TMP57:%.*]] = add nsw i32 [[TMP40]], -1
+; IPSCCP-NEXT:    br label [[BB60]]
+; IPSCCP:       bb58:
+; IPSCCP-NEXT:    [[TMP59:%.*]] = bitcast i16* [[TMP33]] to i8*
+; IPSCCP-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 getelementptr inbounds ([4 x i8], [4 x i8]* @global.11, i64 0, i64 0), i8* align 2 [[TMP59]], i64 4, i1 false)
+; IPSCCP-NEXT:    br label [[BB60]]
+; IPSCCP:       bb60:
+; IPSCCP-NEXT:    [[TMP61:%.*]] = phi i32 [ [[TMP57]], [[BB56]] ], [ [[TMP40]], [[BB39]] ], [ [[TMP11]], [[BB58]] ]
+; IPSCCP-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0
+; IPSCCP-NEXT:    [[TMP63:%.*]] = add i32 [[TMP7]], 1
+; IPSCCP-NEXT:    [[TMP64:%.*]] = mul i32 [[TMP63]], 4
+; IPSCCP-NEXT:    [[TMP65:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP62]], i32 [[TMP64]])
+; IPSCCP-NEXT:    br label [[BB66]]
+; IPSCCP:       bb66:
+; IPSCCP-NEXT:    [[TMP67:%.*]] = phi i8* [ [[TMP36]], [[BB35]] ], [ null, [[BB60]] ]
+; IPSCCP-NEXT:    ret i8* [[TMP67]]
+;
+bb:
+  %tmp = lshr i32 %arg1, 16
+  %tmp2 = xor i32 %tmp, %arg1
+  %tmp3 = and i32 %tmp2, 65535
+  %tmp4 = mul i32 %arg1, 8
+  %tmp5 = getelementptr inbounds %struct.blam.2, %struct.blam.2* %arg, i32 0, i32 1
+  %tmp6 = load i32, i32* %tmp5, align 8
+  %tmp7 = and i32 %tmp4, %tmp6
+  br label %bb8
+
+bb8:                                              ; preds = %bb29, %bb
+  %tmp9 = phi i8* [ undef, %bb ], [ %tmp17, %bb29 ]
+  %tmp10 = phi i16* [ undef, %bb ], [ %tmp18, %bb29 ]
+  %tmp11 = phi i32 [ 0, %bb ], [ %tmp30, %bb29 ]
+  %c.1 = icmp slt i32 %tmp11, 8
+  br i1 %c.1, label %bb13, label %bb31
+
+bb13:                                             ; preds = %bb8
+  %tmp14 = getelementptr inbounds %struct.blam.2, %struct.blam.2* %arg, i32 0, i32 0
+  %tmp15 = add i32 %tmp7, %tmp11
+  %tmp16 = mul i32 %tmp15, 4
+  %tmp17 = call dereferenceable(1) i8* @spam(%struct.baz.1* %tmp14, i32 %tmp16)
+  %tmp18 = bitcast i8* %tmp17 to i16*
+  %tmp19 = getelementptr inbounds i8, i8* %tmp17, i64 2
+  %tmp20 = load i8, i8* %tmp19, align 1
+  %tmp21 = zext i8 %tmp20 to i32
+  %tmp22 = icmp eq i32 %tmp21, 0
+  br i1 %tmp22, label %bb23, label %bb25
+
+bb23:                                             ; preds = %bb13
+  %tmp24 = trunc i32 %tmp3 to i16
+  store i16 %tmp24, i16* %tmp18, align 2
+  br label %bb31
+
+bb25:                                             ; preds = %bb13
+  %tmp26 = load i16, i16* %tmp18, align 2
+  %tmp27 = zext i16 %tmp26 to i32
+  %tmp28 = icmp eq i32 %tmp27, %tmp3
+  br i1 %tmp28, label %bb31, label %bb29
+
+bb29:                                             ; preds = %bb25
+  %tmp30 = add nsw i32 %tmp11, 1
+  br label %bb8
+
+bb31:                                             ; preds = %bb25, %bb23, %bb8
+  %tmp32 = phi i8* [ %tmp17, %bb23 ], [ %tmp17, %bb25 ], [ %tmp9, %bb8 ]
+  %tmp33 = phi i16* [ %tmp18, %bb23 ], [ %tmp18, %bb25 ], [ %tmp10, %bb8 ]
+  %tmp34 = icmp eq i32 %tmp11, 0
+  br i1 %tmp34, label %bb35, label %bb37
+
+bb35:                                             ; preds = %bb31
+  %tmp36 = getelementptr inbounds i8, i8* %tmp32, i64 1
+  br label %bb66
+
+bb37:                                             ; preds = %bb31
+  %c.2 = icmp eq i32 %tmp11, 8
+  br i1 %c.2, label %bb39, label %bb58
+
+bb39:                                             ; preds = %bb37
+  %tmp40 = add nsw i32 %tmp11, -1
+  %tmp41 = trunc i32 %tmp3 to i16
+  store i16 %tmp41, i16* bitcast ([4 x i8]* @global.11 to i16*), align 1
+  %tmp42 = getelementptr inbounds %struct.blam.2, %struct.blam.2* %arg, i32 0, i32 0
+  %tmp43 = add i32 %tmp7, %tmp40
+  %tmp44 = mul i32 %tmp43, 4
+  %tmp45 = add i32 %tmp44, 2
+  %tmp46 = call dereferenceable(1) i8* @spam(%struct.baz.1* %tmp42, i32 %tmp45)
+  %tmp47 = load i8, i8* %tmp46, align 1
+  %tmp48 = zext i8 %tmp47 to i32
+  %tmp49 = sub i32 %tmp43, 1
+  %tmp50 = mul i32 %tmp49, 4
+  %tmp51 = add i32 %tmp50, 2
+  %tmp52 = call dereferenceable(1) i8* @spam(%struct.baz.1* %tmp42, i32 %tmp51)
+  %tmp53 = load i8, i8* %tmp52, align 1
+  %tmp54 = zext i8 %tmp53 to i32
+  %tmp55 = icmp sgt i32 %tmp48, %tmp54
+  br i1 %tmp55, label %bb56, label %bb60
+
+bb56:                                             ; preds = %bb39
+  %tmp57 = add nsw i32 %tmp40, -1
+  br label %bb60
+
+bb58:                                             ; preds = %bb37
+  %tmp59 = bitcast i16* %tmp33 to i8*
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 getelementptr inbounds ([4 x i8], [4 x i8]* @global.11, i64 0, i64 0), i8* align 2 %tmp59, i64 4, i1 false)
+  br label %bb60
+
+bb60:                                             ; preds = %bb58, %bb56, %bb39
+  %tmp61 = phi i32 [ %tmp57, %bb56 ], [ %tmp40, %bb39 ], [ %tmp11, %bb58 ]
+  %tmp62 = getelementptr inbounds %struct.blam.2, %struct.blam.2* %arg, i32 0, i32 0
+  %tmp63 = add i32 %tmp7, 1
+  %tmp64 = mul i32 %tmp63, 4
+  %tmp65 = call dereferenceable(1) i8* @spam(%struct.baz.1* %tmp62, i32 %tmp64)
+  br label %bb66
+
+bb66:                                             ; preds = %bb60, %bb35
+  %tmp67 = phi i8* [ %tmp36, %bb35 ], [ null, %bb60 ]
+  ret i8* %tmp67
+}


        


More information about the llvm-commits mailing list