1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -mergeicmps -verify-dom-info -mtriple=x86_64-unknown-unknown -S | FileCheck %s --check-prefix=X86 3 4%S = type { i32, i32, i32, i32 } 5 6declare void @foo(...) 7 8; We can discard %entry and %land.rhs.i, but still merge the last 2 blocks. 9define zeroext i1 @opeq1( 10; X86-LABEL: @opeq1( 11; X86-NEXT: entry: 12; X86-NEXT: [[FIRST_I:%.*]] = getelementptr inbounds [[S:%.*]], %S* [[A:%.*]], i64 0, i32 0 13; X86-NEXT: [[TMP0:%.*]] = load i32, i32* [[FIRST_I]], align 4 14; X86-NEXT: [[FIRST1_I:%.*]] = getelementptr inbounds [[S]], %S* [[B:%.*]], i64 0, i32 0 15; X86-NEXT: [[TMP1:%.*]] = load i32, i32* [[FIRST1_I]], align 4 16; X86-NEXT: call void (...) @foo() 17; X86-NEXT: [[CMP_I:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] 18; X86-NEXT: br i1 [[CMP_I]], label [[LAND_RHS_I:%.*]], label [[OPEQ1_EXIT:%.*]] 19; X86: land.rhs.i: 20; X86-NEXT: [[SECOND_I:%.*]] = getelementptr inbounds [[S]], %S* [[A]], i64 0, i32 1 21; X86-NEXT: [[TMP2:%.*]] = load i32, i32* [[SECOND_I]], align 4 22; X86-NEXT: [[SECOND2_I:%.*]] = getelementptr inbounds [[S]], %S* [[B]], i64 0, i32 1 23; X86-NEXT: [[TMP3:%.*]] = load i32, i32* [[SECOND2_I]], align 4 24; X86-NEXT: call void (...) @foo() 25; X86-NEXT: [[CMP2_I:%.*]] = icmp eq i32 [[TMP2]], [[TMP3]] 26; X86-NEXT: br i1 [[CMP2_I]], label %"land.rhs.i.2+land.rhs.i.3", label [[OPEQ1_EXIT]] 27; X86: "land.rhs.i.2+land.rhs.i.3": 28; X86-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[S]], %S* [[A]], i64 0, i32 2 29; X86-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[S]], %S* [[B]], i64 0, i32 2 30; X86-NEXT: [[CSTR:%.*]] = bitcast i32* [[TMP4]] to i8* 31; X86-NEXT: [[CSTR1:%.*]] = bitcast i32* [[TMP5]] to i8* 32; X86-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* [[CSTR]], i8* [[CSTR1]], i64 8) 33; X86-NEXT: [[TMP6:%.*]] = icmp eq i32 [[MEMCMP]], 0 34; X86-NEXT: br label [[OPEQ1_EXIT]] 35; X86: opeq1.exit: 36; X86-NEXT: [[TMP7:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ false, [[LAND_RHS_I]] ], [ [[TMP6]], %"land.rhs.i.2+land.rhs.i.3" ] 37; X86-NEXT: ret i1 [[TMP7]] 38; 39 %S* nocapture readonly dereferenceable(16) %a, 40 %S* nocapture readonly dereferenceable(16) %b) local_unnamed_addr nofree nosync { 41entry: 42 %first.i = getelementptr inbounds %S, %S* %a, i64 0, i32 0 43 %0 = load i32, i32* %first.i, align 4 44 %first1.i = getelementptr inbounds %S, %S* %b, i64 0, i32 0 45 %1 = load i32, i32* %first1.i, align 4 46 ; Does other work. 47 call void (...) @foo() 48 %cmp.i = icmp eq i32 %0, %1 49 br i1 %cmp.i, label %land.rhs.i, label %opeq1.exit 50 51land.rhs.i: 52 %second.i = getelementptr inbounds %S, %S* %a, i64 0, i32 1 53 %2 = load i32, i32* %second.i, align 4 54 %second2.i = getelementptr inbounds %S, %S* %b, i64 0, i32 1 55 %3 = load i32, i32* %second2.i, align 4 56 ; Does other work. 57 call void (...) @foo() 58 %cmp2.i = icmp eq i32 %2, %3 59 br i1 %cmp2.i, label %land.rhs.i.2, label %opeq1.exit 60 61land.rhs.i.2: 62 %third.i = getelementptr inbounds %S, %S* %a, i64 0, i32 2 63 %4 = load i32, i32* %third.i, align 4 64 %third2.i = getelementptr inbounds %S, %S* %b, i64 0, i32 2 65 %5 = load i32, i32* %third2.i, align 4 66 %cmp3.i = icmp eq i32 %4, %5 67 br i1 %cmp3.i, label %land.rhs.i.3, label %opeq1.exit 68 69land.rhs.i.3: 70 %fourth.i = getelementptr inbounds %S, %S* %a, i64 0, i32 3 71 %6 = load i32, i32* %fourth.i, align 4 72 %fourth2.i = getelementptr inbounds %S, %S* %b, i64 0, i32 3 73 %7 = load i32, i32* %fourth2.i, align 4 74 %cmp4.i = icmp eq i32 %6, %7 75 br label %opeq1.exit 76 77opeq1.exit: 78 %8 = phi i1 [ false, %entry ], [ false, %land.rhs.i] , [ false, %land.rhs.i.2 ], [ %cmp4.i, %land.rhs.i.3 ] 79 ret i1 %8 80} 81