1; RUN: opt < %s -jump-threading -S | FileCheck %s 2; Test whether two consecutive switches with identical structures assign the 3; proper value to the proper variable. This is really testing 4; Instruction::isIdenticalToWhenDefined, as previously that function was 5; returning true if the value part of the operands of two phis were identical, 6; even if the incoming blocks were not. 7; NB: this function should be pruned down more. 8 9%struct._GList = type { i8*, %struct._GList*, %struct._GList* } 10%struct.filter_def = type { i8*, i8* } 11 12@capture_filters = external hidden global %struct._GList*, align 8 13@display_filters = external hidden global %struct._GList*, align 8 14@.str2 = external hidden unnamed_addr constant [10 x i8], align 1 15@__PRETTY_FUNCTION__.copy_filter_list = external hidden unnamed_addr constant [62 x i8], align 1 16@.str12 = external hidden unnamed_addr constant [22 x i8], align 1 17@.str13 = external hidden unnamed_addr constant [31 x i8], align 1 18@capture_edited_filters = external hidden global %struct._GList*, align 8 19@display_edited_filters = external hidden global %struct._GList*, align 8 20@__PRETTY_FUNCTION__.get_filter_list = external hidden unnamed_addr constant [44 x i8], align 1 21 22declare void @g_assertion_message(i8*, i8*, i32, i8*, i8*) noreturn 23 24declare void @g_free(i8*) 25 26declare %struct._GList* @g_list_first(%struct._GList*) 27 28declare noalias i8* @g_malloc(i64) 29 30define void @copy_filter_list(i32 %dest_type, i32 %src_type) nounwind uwtable ssp { 31entry: 32 br label %do.body 33 34do.body: ; preds = %entry 35 %cmp = icmp ne i32 %dest_type, %src_type 36 br i1 %cmp, label %if.then, label %if.else 37 38if.then: ; preds = %do.body 39 br label %if.end 40 41if.else: ; preds = %do.body 42 call void @g_assertion_message_expr(i8* null, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str2, i32 0, i32 0), i32 581, i8* getelementptr inbounds ([62 x i8], [62 x i8]* @__PRETTY_FUNCTION__.copy_filter_list, i32 0, i32 0), i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str12, i32 0, i32 0)) noreturn 43 unreachable 44 45if.end: ; preds = %if.then 46 br label %do.end 47 48do.end: ; preds = %if.end 49 switch i32 %dest_type, label %sw.default.i [ 50 i32 0, label %sw.bb.i 51 i32 1, label %sw.bb1.i 52 i32 2, label %sw.bb2.i 53 i32 3, label %sw.bb3.i 54 ] 55 56sw.bb.i: ; preds = %do.end 57 br label %get_filter_list.exit 58 59sw.bb1.i: ; preds = %do.end 60 br label %get_filter_list.exit 61 62sw.bb2.i: ; preds = %do.end 63 br label %get_filter_list.exit 64 65sw.bb3.i: ; preds = %do.end 66 br label %get_filter_list.exit 67 68sw.default.i: ; preds = %do.end 69 call void @g_assertion_message(i8* null, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str2, i32 0, i32 0), i32 408, i8* getelementptr inbounds ([44 x i8], [44 x i8]* @__PRETTY_FUNCTION__.get_filter_list, i32 0, i32 0), i8* null) noreturn nounwind 70 unreachable 71 72get_filter_list.exit: ; preds = %sw.bb3.i, %sw.bb2.i, %sw.bb1.i, %sw.bb.i 73 %0 = phi %struct._GList** [ @display_edited_filters, %sw.bb3.i ], [ @capture_edited_filters, %sw.bb2.i ], [ @display_filters, %sw.bb1.i ], [ @capture_filters, %sw.bb.i ] 74 switch i32 %src_type, label %sw.default.i5 [ 75 i32 0, label %sw.bb.i1 76 i32 1, label %sw.bb1.i2 77 i32 2, label %sw.bb2.i3 78 i32 3, label %sw.bb3.i4 79 ] 80 81sw.bb.i1: ; preds = %get_filter_list.exit 82 br label %get_filter_list.exit6 83 84sw.bb1.i2: ; preds = %get_filter_list.exit 85 br label %get_filter_list.exit6 86 87sw.bb2.i3: ; preds = %get_filter_list.exit 88 br label %get_filter_list.exit6 89 90sw.bb3.i4: ; preds = %get_filter_list.exit 91 br label %get_filter_list.exit6 92 93sw.default.i5: ; preds = %get_filter_list.exit 94 call void @g_assertion_message(i8* null, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str2, i32 0, i32 0), i32 408, i8* getelementptr inbounds ([44 x i8], [44 x i8]* @__PRETTY_FUNCTION__.get_filter_list, i32 0, i32 0), i8* null) noreturn nounwind 95 unreachable 96 97; CHECK: get_filter_list.exit 98get_filter_list.exit6: ; preds = %sw.bb3.i4, %sw.bb2.i3, %sw.bb1.i2, %sw.bb.i1 99 %1 = phi %struct._GList** [ @display_edited_filters, %sw.bb3.i4 ], [ @capture_edited_filters, %sw.bb2.i3 ], [ @display_filters, %sw.bb1.i2 ], [ @capture_filters, %sw.bb.i1 ] 100; CHECK: %2 = load 101 %2 = load %struct._GList*, %struct._GList** %1, align 8 102; We should have jump-threading insert an additional load here for the value 103; coming out of the first switch, which is picked up by a subsequent phi 104; CHECK: %.pr = load %struct._GList*, %struct._GList** %0 105; CHECK-NEXT: br label %while.cond 106 br label %while.cond 107 108; CHECK: while.cond 109while.cond: ; preds = %while.body, %get_filter_list.exit6 110; CHECK: {{= phi .*%.pr}} 111 %3 = load %struct._GList*, %struct._GList** %0, align 8 112; CHECK: tobool 113 %tobool = icmp ne %struct._GList* %3, null 114 br i1 %tobool, label %while.body, label %while.end 115 116while.body: ; preds = %while.cond 117 %4 = load %struct._GList*, %struct._GList** %0, align 8 118 %5 = load %struct._GList*, %struct._GList** %0, align 8 119 %call2 = call %struct._GList* @g_list_first(%struct._GList* %5) 120 %data.i = getelementptr inbounds %struct._GList, %struct._GList* %call2, i32 0, i32 0 121 %6 = load i8*, i8** %data.i, align 8 122 %7 = bitcast i8* %6 to %struct.filter_def* 123 %name.i = getelementptr inbounds %struct.filter_def, %struct.filter_def* %7, i32 0, i32 0 124 %8 = load i8*, i8** %name.i, align 8 125 call void @g_free(i8* %8) nounwind 126 %strval.i = getelementptr inbounds %struct.filter_def, %struct.filter_def* %7, i32 0, i32 1 127 %9 = load i8*, i8** %strval.i, align 8 128 call void @g_free(i8* %9) nounwind 129 %10 = bitcast %struct.filter_def* %7 to i8* 130 call void @g_free(i8* %10) nounwind 131 %call.i = call %struct._GList* @g_list_remove_link(%struct._GList* %4, %struct._GList* %call2) nounwind 132 store %struct._GList* %call.i, %struct._GList** %0, align 8 133 br label %while.cond 134 135while.end: ; preds = %while.cond 136 br label %do.body4 137 138do.body4: ; preds = %while.end 139 %11 = load %struct._GList*, %struct._GList** %0, align 8 140 %call5 = call i32 @g_list_length(%struct._GList* %11) 141 %cmp6 = icmp eq i32 %call5, 0 142 br i1 %cmp6, label %if.then7, label %if.else8 143 144if.then7: ; preds = %do.body4 145 br label %if.end9 146 147if.else8: ; preds = %do.body4 148 call void @g_assertion_message_expr(i8* null, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str2, i32 0, i32 0), i32 600, i8* getelementptr inbounds ([62 x i8], [62 x i8]* @__PRETTY_FUNCTION__.copy_filter_list, i32 0, i32 0), i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str13, i32 0, i32 0)) noreturn 149 unreachable 150 151if.end9: ; preds = %if.then7 152 br label %do.end10 153 154do.end10: ; preds = %if.end9 155 br label %while.cond11 156 157while.cond11: ; preds = %cond.end, %do.end10 158 %cond10 = phi %struct._GList* [ %cond, %cond.end ], [ %2, %do.end10 ] 159 %tobool12 = icmp ne %struct._GList* %cond10, null 160 br i1 %tobool12, label %while.body13, label %while.end16 161 162while.body13: ; preds = %while.cond11 163 %data = getelementptr inbounds %struct._GList, %struct._GList* %cond10, i32 0, i32 0 164 %12 = load i8*, i8** %data, align 8 165 %13 = bitcast i8* %12 to %struct.filter_def* 166 %14 = load %struct._GList*, %struct._GList** %0, align 8 167 %name = getelementptr inbounds %struct.filter_def, %struct.filter_def* %13, i32 0, i32 0 168 %15 = load i8*, i8** %name, align 8 169 %strval = getelementptr inbounds %struct.filter_def, %struct.filter_def* %13, i32 0, i32 1 170 %16 = load i8*, i8** %strval, align 8 171 %call.i7 = call noalias i8* @g_malloc(i64 16) nounwind 172 %17 = bitcast i8* %call.i7 to %struct.filter_def* 173 %call1.i = call noalias i8* @g_strdup(i8* %15) nounwind 174 %name.i8 = getelementptr inbounds %struct.filter_def, %struct.filter_def* %17, i32 0, i32 0 175 store i8* %call1.i, i8** %name.i8, align 8 176 %call2.i = call noalias i8* @g_strdup(i8* %16) nounwind 177 %strval.i9 = getelementptr inbounds %struct.filter_def, %struct.filter_def* %17, i32 0, i32 1 178 store i8* %call2.i, i8** %strval.i9, align 8 179 %18 = bitcast %struct.filter_def* %17 to i8* 180 %call3.i = call %struct._GList* @g_list_append(%struct._GList* %14, i8* %18) nounwind 181 store %struct._GList* %call3.i, %struct._GList** %0, align 8 182 %tobool15 = icmp ne %struct._GList* %cond10, null 183 br i1 %tobool15, label %cond.true, label %cond.false 184 185cond.true: ; preds = %while.body13 186 %next = getelementptr inbounds %struct._GList, %struct._GList* %cond10, i32 0, i32 1 187 %19 = load %struct._GList*, %struct._GList** %next, align 8 188 br label %cond.end 189 190cond.false: ; preds = %while.body13 191 br label %cond.end 192 193cond.end: ; preds = %cond.false, %cond.true 194 %cond = phi %struct._GList* [ %19, %cond.true ], [ null, %cond.false ] 195 br label %while.cond11 196 197while.end16: ; preds = %while.cond11 198 ret void 199} 200 201declare void @g_assertion_message_expr(i8*, i8*, i32, i8*, i8*) noreturn 202 203declare i32 @g_list_length(%struct._GList*) 204 205declare noalias i8* @g_strdup(i8*) 206 207declare %struct._GList* @g_list_append(%struct._GList*, i8*) 208 209declare %struct._GList* @g_list_remove_link(%struct._GList*, %struct._GList*) 210