From 9cd68bfa0e49f755a0cc90b27025fa2e48083050 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 14 Apr 2020 18:55:39 +0100 Subject: [PATCH] [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. --- .../test/Transforms/SCCP/conditions-ranges.ll | 153 ++++++ .../Transforms/SCCP/constant-range-struct.ll | 164 +++++++ llvm/test/Transforms/SCCP/widening.ll | 437 ++++++++++++++++++ 3 files changed, 754 insertions(+) create mode 100644 llvm/test/Transforms/SCCP/constant-range-struct.ll 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] }> + +@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 +}