diff --git a/llvm/test/Transforms/NewGVN/load_coercion_replace_load_with_phi.ll b/llvm/test/Transforms/NewGVN/load_coercion_replace_load_with_phi.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/load_coercion_replace_load_with_phi.ll @@ -0,0 +1,1290 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -gvn < %s | FileCheck %s -check-prefixes=GVN,OLDGVN +; RUN: opt -S -newgvn < %s | FileCheck %s -check-prefixes=GVN,NEWGVN + +define i32 @test1(i32* %P, i32 %V1, i1 %Cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test1( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: store i32 [[V1:%.*]], i32* [[P:%.*]], align 4 +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: store i32 13, i32* [[P]], align 4 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V2:%.*]] = phi i32 [ 13, [[F]] ], [ [[V1]], [[T]] ] +; OLDGVN-NEXT: ret i32 [[V2]] +; +; NEWGVN-LABEL: @test1( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: store i32 [[V1:%.*]], i32* [[P:%.*]], align 4 +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: store i32 13, i32* [[P]], align 4 +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[V2:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: ret i32 [[V2]] +; +Entry: + br i1 %Cond, label %T, label %F + +T: + store i32 %V1, i32* %P + br label %Exit + +F: + store i32 13, i32* %P + br label %Exit + +Exit: + %V2 = load i32, i32* %P + ret i32 %V2 +} + +define i8 @test2(i32* %P, i1 %Cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test2( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to float* +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: store i32 42, i32* [[P]], align 4 +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: store float 1.000000e+00, float* [[P1]], align 4 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V2:%.*]] = phi i8 [ 0, [[F]] ], [ 42, [[T]] ] +; OLDGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P]] to i8* +; OLDGVN-NEXT: [[V3:%.*]] = add i8 [[V2]], [[V2]] +; OLDGVN-NEXT: ret i8 [[V3]] +; +; NEWGVN-LABEL: @test2( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to float* +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: store i32 42, i32* [[P]], align 4 +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: store float 1.000000e+00, float* [[P1]], align 4 +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[PHI:%.*]] = phi i8 [ 0, [[F]] ], [ 42, [[T]] ] +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P]] to i8* +; NEWGVN-NEXT: [[V2:%.*]] = load i8, i8* [[P2]], align 1 +; NEWGVN-NEXT: [[V3:%.*]] = add i8 [[V2]], [[PHI]] +; NEWGVN-NEXT: ret i8 [[V3]] +; +Entry: + %P1 = bitcast i32* %P to float* + br i1 %Cond, label %T, label %F + +T: + store i32 42, i32* %P + br label %Exit + +F: + store float 1.0, float* %P1 + br label %Exit + +Exit: + %Phi = phi i8 [ 0, %F ], [ 42, %T ] + %P2 = bitcast i32* %P to i8* + %V2 = load i8, i8* %P2 + %V3 = add i8 %V2, %Phi + ret i8 %V3 +} + +define i8 @test3(i32* %P, i1 %Cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test3( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8* +; OLDGVN-NEXT: [[P4:%.*]] = getelementptr i8, i8* [[P3]], i32 2 +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: store i32 42, i32* [[P]], align 4 +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: [[V4_PRE:%.*]] = load i8, i8* [[P4]], align 1 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V4:%.*]] = phi i8 [ [[V4_PRE]], [[F]] ], [ 0, [[T]] ] +; OLDGVN-NEXT: ret i8 [[V4]] +; +; NEWGVN-LABEL: @test3( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8* +; NEWGVN-NEXT: [[P4:%.*]] = getelementptr i8, i8* [[P3]], i32 2 +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: store i32 42, i32* [[P]], align 4 +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[V4:%.*]] = load i8, i8* [[P4]], align 1 +; NEWGVN-NEXT: ret i8 [[V4]] +; +Entry: + %P3 = bitcast i32* %P to i8* + %P4 = getelementptr i8, i8* %P3, i32 2 + br i1 %Cond, label %T, label %F + +T: + store i32 42, i32* %P + br label %Exit + +F: + br label %Exit + +Exit: + %V4 = load i8, i8* %P4 + ret i8 %V4 +} + +define i32 @test4(i32* %P, i1 %Cond1, i1 %Cond2) { +; Entry +; / \ +; T F +; | / \ +; | F1 F2 +; \ | | +; v v v +; Exit +; +; GVN-LABEL: @test4( +; GVN-NEXT: Entry: +; GVN-NEXT: br i1 [[COND1:%.*]], label [[T:%.*]], label [[F:%.*]] +; GVN: T: +; GVN-NEXT: store i32 42, i32* [[P:%.*]], align 4 +; GVN-NEXT: br label [[EXIT:%.*]] +; GVN: F: +; GVN-NEXT: br i1 [[COND2:%.*]], label [[F1:%.*]], label [[F2:%.*]] +; GVN: F1: +; GVN-NEXT: br label [[EXIT]] +; GVN: F2: +; GVN-NEXT: br label [[EXIT]] +; GVN: Exit: +; GVN-NEXT: [[PHI:%.*]] = phi i32 [ 1, [[T]] ], [ 2, [[F1]] ], [ 3, [[F2]] ] +; GVN-NEXT: [[V1:%.*]] = load i32, i32* [[P]], align 4 +; GVN-NEXT: [[V2:%.*]] = add i32 [[PHI]], [[V1]] +; GVN-NEXT: ret i32 [[V2]] +; +Entry: + br i1 %Cond1, label %T, label %F + +T: + store i32 42, i32* %P + br label %Exit + +F: + br i1 %Cond2, label %F1, label %F2 + +F1: + br label %Exit + +F2: + br label %Exit + +Exit: + %Phi = phi i32 [1, %T], [2, %F1], [3, %F2] + %V1 = load i32, i32* %P + %V2 = add i32 %Phi, %V1 + ret i32 %V2 +} + +define i32 @test5(i32* %P, i1 %Cond1, i1 %Cond2) { +; Entry +; / \ +; T F +; | / \ +; | F1 F2 +; \ | | +; v v v +; Exit +; +; OLDGVN-LABEL: @test5( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: br i1 [[COND1:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: store i32 42, i32* [[P:%.*]], align 4 +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: br i1 [[COND2:%.*]], label [[F1:%.*]], label [[F2:%.*]] +; OLDGVN: F1: +; OLDGVN-NEXT: store i32 13, i32* [[P]], align 4 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: F2: +; OLDGVN-NEXT: [[V1_PRE:%.*]] = load i32, i32* [[P]], align 4 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V1:%.*]] = phi i32 [ 42, [[T]] ], [ 13, [[F1]] ], [ [[V1_PRE]], [[F2]] ] +; OLDGVN-NEXT: [[PHI:%.*]] = phi i32 [ 1, [[T]] ], [ 2, [[F1]] ], [ 3, [[F2]] ] +; OLDGVN-NEXT: [[V2:%.*]] = add i32 [[PHI]], [[V1]] +; OLDGVN-NEXT: ret i32 [[V2]] +; +; NEWGVN-LABEL: @test5( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: br i1 [[COND1:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: store i32 42, i32* [[P:%.*]], align 4 +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: br i1 [[COND2:%.*]], label [[F1:%.*]], label [[F2:%.*]] +; NEWGVN: F1: +; NEWGVN-NEXT: store i32 13, i32* [[P]], align 4 +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: F2: +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[PHI:%.*]] = phi i32 [ 1, [[T]] ], [ 2, [[F1]] ], [ 3, [[F2]] ] +; NEWGVN-NEXT: [[V1:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: [[V2:%.*]] = add i32 [[PHI]], [[V1]] +; NEWGVN-NEXT: ret i32 [[V2]] +; +Entry: + br i1 %Cond1, label %T, label %F + +T: + store i32 42, i32* %P + br label %Exit + +F: + br i1 %Cond2, label %F1, label %F2 + +F1: + store i32 13, i32* %P + br label %Exit + +F2: + br label %Exit + +Exit: + %Phi = phi i32 [1, %T], [2, %F1], [3, %F2] + %V1 = load i32, i32* %P + %V2 = add i32 %Phi, %V1 + ret i32 %V2 +} + +define i32 @test6(i32* %P, i1 %Cond1, i1 %Cond2) { +; Entry __ +; | \ / | +; | v v | +; | Loop | +; | / \__| +; v v +; Exit +; +; OLDGVN-LABEL: @test6( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: store i32 42, i32* [[P:%.*]], align 4 +; OLDGVN-NEXT: br i1 [[COND1:%.*]], label [[LOOP:%.*]], label [[EXIT:%.*]] +; OLDGVN: Loop: +; OLDGVN-NEXT: store i32 13, i32* [[P]], align 4 +; OLDGVN-NEXT: br i1 [[COND2:%.*]], label [[LOOP]], label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V:%.*]] = phi i32 [ 13, [[LOOP]] ], [ 42, [[ENTRY:%.*]] ] +; OLDGVN-NEXT: ret i32 [[V]] +; +; NEWGVN-LABEL: @test6( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: store i32 42, i32* [[P:%.*]], align 4 +; NEWGVN-NEXT: br i1 [[COND1:%.*]], label [[LOOP:%.*]], label [[EXIT:%.*]] +; NEWGVN: Loop: +; NEWGVN-NEXT: store i32 13, i32* [[P]], align 4 +; NEWGVN-NEXT: br i1 [[COND2:%.*]], label [[LOOP]], label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[V:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: ret i32 [[V]] +; +Entry: + store i32 42, i32* %P + br i1 %Cond1, label %Loop, label %Exit + +Loop: + store i32 13, i32* %P + br i1 %Cond2, label %Loop, label %Exit + +Exit: + %V = load i32, i32* %P + ret i32 %V +} + +define i32 @test7(i32* %P, i1 %Cond1, i1 %Cond2, i1 %Cond3) { +; Entry +; | +; +--Outer.Loop<-------+ +; | | _ | +; | | / | | +; | | v | | +; | Inner.Loop | | +; | | \_| | +; | | | +; +->Outer.Loop.Latch--+ +; | +; Exit +; +; OLDGVN-LABEL: @test7( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: br label [[OUTER_LOOP:%.*]] +; OLDGVN: Outer.Loop: +; OLDGVN-NEXT: store i32 42, i32* [[P:%.*]], align 4 +; OLDGVN-NEXT: br i1 [[COND1:%.*]], label [[INNER_LOOP:%.*]], label [[OUTER_LOOP_LATCH:%.*]] +; OLDGVN: Inner.Loop: +; OLDGVN-NEXT: store i32 13, i32* [[P]], align 4 +; OLDGVN-NEXT: br i1 [[COND2:%.*]], label [[INNER_LOOP]], label [[OUTER_LOOP_LATCH]] +; OLDGVN: Outer.Loop.Latch: +; OLDGVN-NEXT: [[V2:%.*]] = phi i32 [ 13, [[INNER_LOOP]] ], [ 42, [[OUTER_LOOP]] ] +; OLDGVN-NEXT: [[PHI:%.*]] = phi i32 [ 100, [[INNER_LOOP]] ], [ 200, [[OUTER_LOOP]] ] +; OLDGVN-NEXT: [[V3:%.*]] = add i32 [[V2]], [[PHI]] +; OLDGVN-NEXT: br i1 [[COND3:%.*]], label [[OUTER_LOOP]], label [[EXIT:%.*]] +; OLDGVN: Exit: +; OLDGVN-NEXT: ret i32 [[V3]] +; +; NEWGVN-LABEL: @test7( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: br label [[OUTER_LOOP:%.*]] +; NEWGVN: Outer.Loop: +; NEWGVN-NEXT: store i32 42, i32* [[P:%.*]], align 4 +; NEWGVN-NEXT: br i1 [[COND1:%.*]], label [[INNER_LOOP:%.*]], label [[OUTER_LOOP_LATCH:%.*]] +; NEWGVN: Inner.Loop: +; NEWGVN-NEXT: store i32 13, i32* [[P]], align 4 +; NEWGVN-NEXT: br i1 [[COND2:%.*]], label [[INNER_LOOP]], label [[OUTER_LOOP_LATCH]] +; NEWGVN: Outer.Loop.Latch: +; NEWGVN-NEXT: [[PHI:%.*]] = phi i32 [ 100, [[INNER_LOOP]] ], [ 200, [[OUTER_LOOP]] ] +; NEWGVN-NEXT: [[V2:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: [[V3:%.*]] = add i32 [[V2]], [[PHI]] +; NEWGVN-NEXT: br i1 [[COND3:%.*]], label [[OUTER_LOOP]], label [[EXIT:%.*]] +; NEWGVN: Exit: +; NEWGVN-NEXT: ret i32 [[V3]] +; +Entry: + br label %Outer.Loop + +Outer.Loop: + store i32 42, i32* %P + br i1 %Cond1, label %Inner.Loop, label %Outer.Loop.Latch + +Inner.Loop: + store i32 13, i32* %P + br i1 %Cond2, label %Inner.Loop, label %Outer.Loop.Latch + +Outer.Loop.Latch: + %Phi = phi i32 [ 100, %Inner.Loop ], [ 200, %Outer.Loop ] + %V2 = load i32, i32* %P + %V3 = add i32 %V2, %Phi + br i1 %Cond3, label %Outer.Loop, label %Exit + +Exit: + ret i32 %V3 +} + +define i32 @test8(i8* %P, i1 %Cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test8( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i8* [[P:%.*]] to <2 x i32>* +; OLDGVN-NEXT: [[V1:%.*]] = load <2 x i32>, <2 x i32>* [[P1]], align 8 +; OLDGVN-NEXT: [[V3:%.*]] = extractelement <2 x i32> [[V1]], i64 1 +; OLDGVN-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[V1]] to i64 +; OLDGVN-NEXT: [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32 +; OLDGVN-NEXT: [[DOTPRE:%.*]] = bitcast i8* [[P]] to i32* +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: [[P2_PHI_TRANS_INSERT:%.*]] = bitcast i8* [[P]] to i32* +; OLDGVN-NEXT: [[V2_PRE:%.*]] = load i32, i32* [[P2_PHI_TRANS_INSERT]], align 4 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[P2_PRE_PHI:%.*]] = phi i32* [ [[P2_PHI_TRANS_INSERT]], [[F]] ], [ [[DOTPRE]], [[T]] ] +; OLDGVN-NEXT: [[V2:%.*]] = phi i32 [ [[V2_PRE]], [[F]] ], [ [[TMP1]], [[T]] ] +; OLDGVN-NEXT: [[PHI:%.*]] = phi i32 [ 100, [[F]] ], [ [[V3]], [[T]] ] +; OLDGVN-NEXT: [[V4:%.*]] = add i32 [[V2]], [[PHI]] +; OLDGVN-NEXT: ret i32 [[V4]] +; +; NEWGVN-LABEL: @test8( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: [[P1:%.*]] = bitcast i8* [[P:%.*]] to <2 x i32>* +; NEWGVN-NEXT: [[V1:%.*]] = load <2 x i32>, <2 x i32>* [[P1]], align 8 +; NEWGVN-NEXT: [[V3:%.*]] = extractelement <2 x i32> [[V1]], i64 1 +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[PHI:%.*]] = phi i32 [ 100, [[F]] ], [ [[V3]], [[T]] ] +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i8* [[P]] to i32* +; NEWGVN-NEXT: [[V2:%.*]] = load i32, i32* [[P2]], align 4 +; NEWGVN-NEXT: [[V4:%.*]] = add i32 [[V2]], [[PHI]] +; NEWGVN-NEXT: ret i32 [[V4]] +; +Entry: + br i1 %Cond, label %T, label %F + +T: + %P1 = bitcast i8* %P to <2 x i32>* + %V1 = load <2 x i32>, <2 x i32>* %P1 + %V3 = extractelement <2 x i32> %V1, i64 1 + br label %Exit + +F: + br label %Exit + +Exit: + %Phi = phi i32 [100, %F], [%V3, %T] + %P2 = bitcast i8* %P to i32* + %V2 = load i32, i32* %P2 + %V4 = add i32 %V2, %Phi + ret i32 %V4 +} + +define i32 @test9(i32* %P, i1 %Cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test9( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to <2 x i32>* +; OLDGVN-NEXT: [[V4_PRE:%.*]] = load i32, i32* [[P]], align 4 +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P]] to <2 x i32>* +; OLDGVN-NEXT: [[V2:%.*]] = load <2 x i32>, <2 x i32>* [[P2]], align 8 +; OLDGVN-NEXT: [[V3:%.*]] = extractelement <2 x i32> [[V2]], i64 1 +; OLDGVN-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[V2]] to i64 +; OLDGVN-NEXT: [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V4:%.*]] = phi i32 [ [[V4_PRE]], [[T]] ], [ [[TMP1]], [[F]] ] +; OLDGVN-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[T]] ], [ [[V3]], [[F]] ] +; OLDGVN-NEXT: [[V5:%.*]] = add i32 [[V4]], [[PHI]] +; OLDGVN-NEXT: ret i32 [[V5]] +; +; NEWGVN-LABEL: @test9( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P:%.*]] to <2 x i32>* +; NEWGVN-NEXT: [[V2:%.*]] = load <2 x i32>, <2 x i32>* [[P2]], align 8 +; NEWGVN-NEXT: [[V3:%.*]] = extractelement <2 x i32> [[V2]], i64 1 +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[T]] ], [ [[V3]], [[F]] ] +; NEWGVN-NEXT: [[V4:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: [[V5:%.*]] = add i32 [[V4]], [[PHI]] +; NEWGVN-NEXT: ret i32 [[V5]] +; +Entry: + br i1 %Cond, label %T, label %F + +T: + %P1 = bitcast i32* %P to <2 x i32>* + %V1 = load <2 x i32>, <2 x i32>* %P1 + br label %Exit + +F: + %P2 = bitcast i32* %P to <2 x i32>* + %V2 = load <2 x i32>, <2 x i32>* %P2 + %V3 = extractelement <2 x i32> %V2, i64 1 + br label %Exit + +Exit: + %Phi = phi i32 [0, %T], [%V3, %F] + %V4 = load i32, i32* %P + %V5 = add i32 %V4, %Phi + ret i32 %V5 +} + +define i32 @test10(i32* %P, i1 %Cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test10( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: [[V1:%.*]] = load i32, i32* [[P:%.*]], align 4 +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P]] to <2 x i32>* +; OLDGVN-NEXT: [[V2:%.*]] = load <2 x i32>, <2 x i32>* [[P2]], align 8 +; OLDGVN-NEXT: [[V3:%.*]] = extractelement <2 x i32> [[V2]], i64 1 +; OLDGVN-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[V2]] to i64 +; OLDGVN-NEXT: [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V4:%.*]] = phi i32 [ [[V1]], [[T]] ], [ [[TMP1]], [[F]] ] +; OLDGVN-NEXT: [[PHI:%.*]] = phi i32 [ [[V1]], [[T]] ], [ [[V3]], [[F]] ] +; OLDGVN-NEXT: [[V5:%.*]] = add i32 [[PHI]], [[PHI]] +; OLDGVN-NEXT: [[V6:%.*]] = add i32 [[V5]], [[V4]] +; OLDGVN-NEXT: ret i32 [[V6]] +; +; NEWGVN-LABEL: @test10( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: [[V1:%.*]] = load i32, i32* [[P:%.*]], align 4 +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P]] to <2 x i32>* +; NEWGVN-NEXT: [[V2:%.*]] = load <2 x i32>, <2 x i32>* [[P2]], align 8 +; NEWGVN-NEXT: [[V3:%.*]] = extractelement <2 x i32> [[V2]], i64 1 +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[PHI:%.*]] = phi i32 [ [[V1]], [[T]] ], [ [[V3]], [[F]] ] +; NEWGVN-NEXT: [[V4:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: [[V5:%.*]] = add i32 [[PHI]], [[PHI]] +; NEWGVN-NEXT: [[V6:%.*]] = add i32 [[V5]], [[V4]] +; NEWGVN-NEXT: ret i32 [[V6]] +; +Entry: + br i1 %Cond, label %T, label %F + +T: + %V1 = load i32, i32* %P + br label %Exit + +F: + %P2 = bitcast i32* %P to <2 x i32>* + %V2 = load <2 x i32>, <2 x i32>* %P2 + %V3 = extractelement <2 x i32> %V2, i64 1 + br label %Exit + +Exit: + %Phi = phi i32 [%V1, %T], [%V3, %F] + %V4 = load i32, i32* %P + %V5 = add i32 %Phi, %Phi + %V6 = add i32 %V5, %V4 + ret i32 %V6 +} + +define i32 @test11(i32* %P, i1 %Cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; GVN-LABEL: @test11( +; GVN-NEXT: Entry: +; GVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; GVN: T: +; GVN-NEXT: [[V1:%.*]] = load i32, i32* [[P:%.*]], align 4 +; GVN-NEXT: br label [[EXIT:%.*]] +; GVN: F: +; GVN-NEXT: br label [[EXIT]] +; GVN: Exit: +; GVN-NEXT: [[PHI:%.*]] = phi i32 [ [[V1]], [[T]] ], [ 0, [[F]] ] +; GVN-NEXT: [[P2:%.*]] = bitcast i32* [[P]] to <2 x i32>* +; GVN-NEXT: [[V2:%.*]] = load <2 x i32>, <2 x i32>* [[P2]], align 8 +; GVN-NEXT: [[V3:%.*]] = extractelement <2 x i32> [[V2]], i64 1 +; GVN-NEXT: [[V5:%.*]] = add i32 [[PHI]], [[V3]] +; GVN-NEXT: ret i32 [[V5]] +; +Entry: + br i1 %Cond, label %T, label %F + +T: + %V1 = load i32, i32* %P + br label %Exit + +F: + br label %Exit + +Exit: + %Phi = phi i32 [%V1, %T], [0, %F] + %P2 = bitcast i32* %P to <2 x i32>* + %V2 = load <2 x i32>, <2 x i32>* %P2 + %V3 = extractelement <2 x i32> %V2, i64 1 + %V5 = add i32 %Phi, %V3 + ret i32 %V5 +} + +define i32 @test12(i32* %P, i1 %Cond1, i1 %Cond2) { +; Entry __ +; | \ / | +; | v v | +; | Loop | +; | / \__| +; v v +; Exit +; +; OLDGVN-LABEL: @test12( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to <2 x i32>* +; OLDGVN-NEXT: [[V1:%.*]] = load <2 x i32>, <2 x i32>* [[P1]], align 8 +; OLDGVN-NEXT: [[V2:%.*]] = extractelement <2 x i32> [[V1]], i64 1 +; OLDGVN-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[V1]] to i64 +; OLDGVN-NEXT: [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32 +; OLDGVN-NEXT: br i1 [[COND1:%.*]], label [[LOOP:%.*]], label [[EXIT:%.*]] +; OLDGVN: Loop: +; OLDGVN-NEXT: br i1 [[COND2:%.*]], label [[LOOP]], label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[PHI:%.*]] = phi i32 [ [[V2]], [[ENTRY:%.*]] ], [ [[TMP1]], [[LOOP]] ] +; OLDGVN-NEXT: ret i32 [[PHI]] +; +; NEWGVN-LABEL: @test12( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to <2 x i32>* +; NEWGVN-NEXT: [[V1:%.*]] = load <2 x i32>, <2 x i32>* [[P1]], align 8 +; NEWGVN-NEXT: [[V2:%.*]] = extractelement <2 x i32> [[V1]], i64 1 +; NEWGVN-NEXT: br i1 [[COND1:%.*]], label [[LOOP:%.*]], label [[EXIT:%.*]] +; NEWGVN: Loop: +; NEWGVN-NEXT: [[V3:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: br i1 [[COND2:%.*]], label [[LOOP]], label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[PHI:%.*]] = phi i32 [ [[V2]], [[ENTRY:%.*]] ], [ [[V3]], [[LOOP]] ] +; NEWGVN-NEXT: ret i32 [[PHI]] +; +Entry: + %P1 = bitcast i32* %P to <2 x i32>* + %V1 = load <2 x i32>, <2 x i32>* %P1 + %V2 = extractelement <2 x i32> %V1, i64 1 + br i1 %Cond1, label %Loop, label %Exit + +Loop: + %V3 = load i32, i32* %P + br i1 %Cond2, label %Loop, label %Exit + +Exit: + %Phi = phi i32 [ %V2, %Entry ], [ %V3, %Loop ] + ret i32 %Phi +} + +define i32 @test13(i32* %P, i1 %Cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test13( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to <4 x i32>* +; OLDGVN-NEXT: [[V1:%.*]] = load <4 x i32>, <4 x i32>* [[P1]], align 16 +; OLDGVN-NEXT: [[V2:%.*]] = extractelement <4 x i32> [[V1]], i64 2 +; OLDGVN-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[V1]] to i128 +; OLDGVN-NEXT: [[TMP1:%.*]] = trunc i128 [[TMP0]] to i32 +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: store i32 13, i32* [[P]], align 4 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V3:%.*]] = phi i32 [ [[TMP1]], [[T]] ], [ 13, [[F]] ] +; OLDGVN-NEXT: [[PHI:%.*]] = phi i32 [ [[V2]], [[T]] ], [ 100, [[F]] ] +; OLDGVN-NEXT: [[V4:%.*]] = add i32 [[PHI]], [[V3]] +; OLDGVN-NEXT: ret i32 [[V4]] +; +; NEWGVN-LABEL: @test13( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to <4 x i32>* +; NEWGVN-NEXT: [[V1:%.*]] = load <4 x i32>, <4 x i32>* [[P1]], align 16 +; NEWGVN-NEXT: [[V2:%.*]] = extractelement <4 x i32> [[V1]], i64 2 +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: store i32 13, i32* [[P]], align 4 +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[PHI:%.*]] = phi i32 [ [[V2]], [[T]] ], [ 100, [[F]] ] +; NEWGVN-NEXT: [[V3:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: [[V4:%.*]] = add i32 [[PHI]], [[V3]] +; NEWGVN-NEXT: ret i32 [[V4]] +; +Entry: + br i1 %Cond, label %T, label %F + +T: + %P1 = bitcast i32* %P to <4 x i32>* + %V1 = load <4 x i32>, <4 x i32>* %P1 + %V2 = extractelement <4 x i32> %V1, i64 2 + br label %Exit + +F: + store i32 13, i32* %P + br label %Exit + +Exit: + %Phi = phi i32 [ %V2, %T ], [ 100, %F ] + %V3 = load i32, i32* %P + %V4 = add i32 %Phi, %V3 + ret i32 %V4 +} + +define i32 @test14(i32* %P, i1 %Cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test14( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to <4 x i32>* +; OLDGVN-NEXT: store <4 x i32> , <4 x i32>* [[P1]], align 16 +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: store i32 100, i32* [[P]], align 4 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V3:%.*]] = phi i32 [ 13, [[T]] ], [ 100, [[F]] ] +; OLDGVN-NEXT: [[V4:%.*]] = add i32 [[V3]], [[V3]] +; OLDGVN-NEXT: ret i32 [[V4]] +; +; NEWGVN-LABEL: @test14( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to <4 x i32>* +; NEWGVN-NEXT: store <4 x i32> , <4 x i32>* [[P1]], align 16 +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: store i32 100, i32* [[P]], align 4 +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[PHI:%.*]] = phi i32 [ 13, [[T]] ], [ 100, [[F]] ] +; NEWGVN-NEXT: [[V3:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: [[V4:%.*]] = add i32 [[PHI]], [[V3]] +; NEWGVN-NEXT: ret i32 [[V4]] +; +Entry: + %P1 = bitcast i32* %P to <4 x i32>* + store <4 x i32> , <4 x i32>* %P1 + br i1 %Cond, label %T, label %F + +T: + %V1 = load <4 x i32>, <4 x i32>* %P1 + %V2 = extractelement <4 x i32> %V1, i64 2 + br label %Exit + +F: + store i32 100, i32* %P + br label %Exit + +Exit: + %Phi = phi i32 [ %V2, %T ], [ 100, %F ] + %V3 = load i32, i32* %P + %V4 = add i32 %Phi, %V3 + ret i32 %V4 +} + +define i32 @test15(i32* %P, i1 %Cond) { +; Entry +; / | +; BB | +; | | +; v v +; Exit +; +; OLDGVN-LABEL: @test15( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: store i32 42, i32* [[P:%.*]], align 4 +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[BB:%.*]], label [[EXIT:%.*]] +; OLDGVN: BB: +; OLDGVN-NEXT: store i32 13, i32* [[P]], align 4 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V1:%.*]] = phi i32 [ 13, [[BB]] ], [ 42, [[ENTRY:%.*]] ] +; OLDGVN-NEXT: ret i32 [[V1]] +; +; NEWGVN-LABEL: @test15( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: store i32 42, i32* [[P:%.*]], align 4 +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[BB:%.*]], label [[EXIT:%.*]] +; NEWGVN: BB: +; NEWGVN-NEXT: store i32 13, i32* [[P]], align 4 +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[V1:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: ret i32 [[V1]] +; +Entry: + store i32 42, i32* %P + br i1 %Cond, label %BB, label %Exit + +BB: + store i32 13, i32* %P + br label %Exit + +Exit: + %V1 = load i32, i32* %P + ret i32 %V1 +} + +define i32 @test16(i32* %P, i1 %Cond) { +; Entry +; / | +; BB | +; | | +; v v +; Exit +; +; OLDGVN-LABEL: @test16( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to <4 x i32>* +; OLDGVN-NEXT: [[V1:%.*]] = load <4 x i32>, <4 x i32>* [[P1]], align 16 +; OLDGVN-NEXT: [[V2:%.*]] = extractelement <4 x i32> [[V1]], i64 2 +; OLDGVN-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[V1]] to i128 +; OLDGVN-NEXT: [[TMP1:%.*]] = trunc i128 [[TMP0]] to i32 +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[BB:%.*]], label [[EXIT:%.*]] +; OLDGVN: BB: +; OLDGVN-NEXT: store i32 13, i32* [[P]], align 4 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V3:%.*]] = phi i32 [ [[TMP1]], [[ENTRY:%.*]] ], [ 13, [[BB]] ] +; OLDGVN-NEXT: [[PHI:%.*]] = phi i32 [ [[V2]], [[ENTRY]] ], [ 100, [[BB]] ] +; OLDGVN-NEXT: [[V4:%.*]] = add i32 [[PHI]], [[V3]] +; OLDGVN-NEXT: ret i32 [[V4]] +; +; NEWGVN-LABEL: @test16( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to <4 x i32>* +; NEWGVN-NEXT: [[V1:%.*]] = load <4 x i32>, <4 x i32>* [[P1]], align 16 +; NEWGVN-NEXT: [[V2:%.*]] = extractelement <4 x i32> [[V1]], i64 2 +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[BB:%.*]], label [[EXIT:%.*]] +; NEWGVN: BB: +; NEWGVN-NEXT: store i32 13, i32* [[P]], align 4 +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[PHI:%.*]] = phi i32 [ [[V2]], [[ENTRY:%.*]] ], [ 100, [[BB]] ] +; NEWGVN-NEXT: [[V3:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: [[V4:%.*]] = add i32 [[PHI]], [[V3]] +; NEWGVN-NEXT: ret i32 [[V4]] +; +Entry: + %P1 = bitcast i32* %P to <4 x i32>* + %V1 = load <4 x i32>, <4 x i32>* %P1 + %V2 = extractelement <4 x i32> %V1, i64 2 + br i1 %Cond, label %BB, label %Exit + +BB: + store i32 13, i32* %P + br label %Exit + +Exit: + %Phi = phi i32 [ %V2, %Entry ], [ 100, %BB ] + %V3 = load i32, i32* %P + %V4 = add i32 %Phi, %V3 + ret i32 %V4 +} + +define i32 @test17(i32* %P, i32 %V, i1 %cond1, i1 %cond2) { +; Entry __ +; / \ v | +; BB Loop | +; \ / \_| +; vv +; Exit +; +; OLDGVN-LABEL: @test17( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: br i1 [[COND1:%.*]], label [[BB:%.*]], label [[LOOP:%.*]] +; OLDGVN: BB: +; OLDGVN-NEXT: store i32 42, i32* [[P:%.*]], align 4 +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: Loop: +; OLDGVN-NEXT: [[PHI:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[V1:%.*]], [[LOOP]] ] +; OLDGVN-NEXT: [[V1]] = add i32 [[V:%.*]], [[PHI]] +; OLDGVN-NEXT: br i1 [[COND2:%.*]], label [[LOOP]], label [[LOOP_EXIT_CRIT_EDGE:%.*]] +; OLDGVN: Loop.Exit_crit_edge: +; OLDGVN-NEXT: [[V2_PRE:%.*]] = load i32, i32* [[P]], align 4 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V2:%.*]] = phi i32 [ [[V2_PRE]], [[LOOP_EXIT_CRIT_EDGE]] ], [ 42, [[BB]] ] +; OLDGVN-NEXT: ret i32 [[V2]] +; +; NEWGVN-LABEL: @test17( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: br i1 [[COND1:%.*]], label [[BB:%.*]], label [[LOOP:%.*]] +; NEWGVN: BB: +; NEWGVN-NEXT: store i32 42, i32* [[P:%.*]], align 4 +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: Loop: +; NEWGVN-NEXT: [[PHI:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[V1:%.*]], [[LOOP]] ] +; NEWGVN-NEXT: [[V1]] = add i32 [[V:%.*]], [[PHI]] +; NEWGVN-NEXT: br i1 [[COND2:%.*]], label [[LOOP]], label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[V2:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: ret i32 [[V2]] +; +Entry: + br i1 %cond1, label %BB, label %Loop + +BB: + store i32 42, i32* %P + br label %Exit + +Loop: + %phi = phi i32 [ 100, %Entry ], [ %V1, %Loop ] + %V1 = add i32 %V, %phi + br i1 %cond2, label %Loop, label %Exit + +Exit: + %V2 = load i32, i32* %P + ret i32 %V2 +} + +define i32 @test18(i32* %P, i1 %Cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test18( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to <4 x i32>* +; OLDGVN-NEXT: [[V1:%.*]] = load <4 x i32>, <4 x i32>* [[P1]], align 16 +; OLDGVN-NEXT: [[V2:%.*]] = extractelement <4 x i32> [[V1]], i64 2 +; OLDGVN-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[V1]] to i128 +; OLDGVN-NEXT: [[TMP1:%.*]] = trunc i128 [[TMP0]] to i32 +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: store <4 x i32> , <4 x i32>* [[P1]], align 16 +; OLDGVN-NEXT: store i32 100, i32* [[P]], align 4 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V4:%.*]] = phi i32 [ [[TMP1]], [[T]] ], [ 100, [[F]] ] +; OLDGVN-NEXT: [[PHI:%.*]] = phi i32 [ [[V2]], [[T]] ], [ 13, [[F]] ] +; OLDGVN-NEXT: [[V5:%.*]] = add i32 [[PHI]], [[V4]] +; OLDGVN-NEXT: ret i32 [[V5]] +; +; NEWGVN-LABEL: @test18( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to <4 x i32>* +; NEWGVN-NEXT: [[V1:%.*]] = load <4 x i32>, <4 x i32>* [[P1]], align 16 +; NEWGVN-NEXT: [[V2:%.*]] = extractelement <4 x i32> [[V1]], i64 2 +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: store <4 x i32> , <4 x i32>* [[P1]], align 16 +; NEWGVN-NEXT: store i32 100, i32* [[P]], align 4 +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[PHI:%.*]] = phi i32 [ [[V2]], [[T]] ], [ 13, [[F]] ] +; NEWGVN-NEXT: [[V4:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: [[V5:%.*]] = add i32 [[PHI]], [[V4]] +; NEWGVN-NEXT: ret i32 [[V5]] +; +Entry: + %P1 = bitcast i32* %P to <4 x i32>* + %V1 = load <4 x i32>, <4 x i32>* %P1 + %V2 = extractelement <4 x i32> %V1, i64 2 + br i1 %Cond, label %T, label %F + +T: + br label %Exit + +F: + store <4 x i32> , <4 x i32>* %P1 + %V3 = load i32, i32* %P + store i32 100, i32* %P + br label %Exit + +Exit: + %Phi = phi i32 [ %V2, %T ], [ %V3, %F ] + %V4 = load i32, i32* %P + %V5 = add i32 %Phi, %V4 + ret i32 %V5 +} + +define i16 @test19(i32* %P, i32 %V, i1 %Cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test19( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: store i32 42, i32* [[P:%.*]], align 4 +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P]] to i16* +; OLDGVN-NEXT: store i16 13, i16* [[P1]], align 2 +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: store i32 [[V:%.*]], i32* [[P]], align 4 +; OLDGVN-NEXT: [[TMP0:%.*]] = trunc i32 [[V]] to i16 +; OLDGVN-NEXT: [[DOTPRE:%.*]] = bitcast i32* [[P]] to i16* +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[P2_PRE_PHI:%.*]] = phi i16* [ [[DOTPRE]], [[F]] ], [ [[P1]], [[T]] ] +; OLDGVN-NEXT: [[V2:%.*]] = phi i16 [ [[TMP0]], [[F]] ], [ 13, [[T]] ] +; OLDGVN-NEXT: ret i16 [[V2]] +; +; NEWGVN-LABEL: @test19( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: store i32 42, i32* [[P:%.*]], align 4 +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P]] to i16* +; NEWGVN-NEXT: store i16 13, i16* [[P1]], align 2 +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: store i32 [[V:%.*]], i32* [[P]], align 4 +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P]] to i16* +; NEWGVN-NEXT: [[V2:%.*]] = load i16, i16* [[P2]], align 2 +; NEWGVN-NEXT: ret i16 [[V2]] +; +Entry: + store i32 42, i32* %P + br i1 %Cond, label %T, label %F + +T: + %P1 = bitcast i32* %P to i16* + store i16 13, i16* %P1 + br label %Exit + +F: + store i32 %V, i32* %P + br label %Exit + +Exit: + %P2 = bitcast i32* %P to i16* + %V2 = load i16, i16* %P2 + ret i16 %V2 +} + +define i32 @test20(i32* %P, i1 %cond1, i1 %cond2) { +; Entry +; / \ +; BB1 BB2 +; | | +; BB3 BB4 +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test20( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to <2 x i32>* +; OLDGVN-NEXT: br i1 [[COND1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] +; OLDGVN: BB1: +; OLDGVN-NEXT: store i32 42, i32* [[P]], align 4 +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: BB2: +; OLDGVN-NEXT: [[V2:%.*]] = load i32, i32* [[P]], align 4 +; OLDGVN-NEXT: [[V5:%.*]] = add i32 [[V2]], 100 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[PHI:%.*]] = phi i32 [ 142, [[BB1]] ], [ [[V5]], [[BB2]] ] +; OLDGVN-NEXT: ret i32 [[PHI]] +; +; NEWGVN-LABEL: @test20( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to <2 x i32>* +; NEWGVN-NEXT: br i1 [[COND1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] +; NEWGVN: BB1: +; NEWGVN-NEXT: store i32 42, i32* [[P]], align 4 +; NEWGVN-NEXT: br label [[BB3:%.*]] +; NEWGVN: BB2: +; NEWGVN-NEXT: [[V2:%.*]] = load i32, i32* [[P]], align 4 +; NEWGVN-NEXT: br label [[BB4:%.*]] +; NEWGVN: BB3: +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: BB4: +; NEWGVN-NEXT: [[V5:%.*]] = add i32 [[V2]], 100 +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[PHI:%.*]] = phi i32 [ 142, [[BB3]] ], [ [[V5]], [[BB4]] ] +; NEWGVN-NEXT: ret i32 [[PHI]] +; +Entry: + %P1 = bitcast i32* %P to <2 x i32>* + %V1 = load <2 x i32>, <2 x i32>* %P1 + br i1 %cond1, label %BB1, label %BB2 + +BB1: + store i32 42, i32* %P + br label %BB3 + +BB2: + %V2 = load i32, i32* %P + br label %BB4 + +BB3: + %V3 = load i32, i32* %P + %V4 = add i32 %V3, 100 + br label %Exit + +BB4: + %V5 = add i32 %V2, 100 + br label %Exit + +Exit: + %phi = phi i32 [ %V4, %BB3 ], [ %V5, %BB4 ] + ret i32 %phi +} + +define i32 @test21(i32* %P1, i32* %P2, i1 %cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test21( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: store i32 42, i32* [[P1:%.*]], align 4 +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: [[V1_PRE:%.*]] = load i32, i32* [[P1]], align 4 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V1:%.*]] = phi i32 [ [[V1_PRE]], [[F]] ], [ 42, [[T]] ] +; OLDGVN-NEXT: [[V2:%.*]] = load i32, i32* [[P2:%.*]], align 4 +; OLDGVN-NEXT: [[V3:%.*]] = add i32 [[V1]], [[V2]] +; OLDGVN-NEXT: ret i32 [[V3]] +; +; NEWGVN-LABEL: @test21( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: store i32 42, i32* [[P1:%.*]], align 4 +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[V1:%.*]] = load i32, i32* [[P1]], align 4 +; NEWGVN-NEXT: [[V2:%.*]] = load i32, i32* [[P2:%.*]], align 4 +; NEWGVN-NEXT: [[V3:%.*]] = add i32 [[V1]], [[V2]] +; NEWGVN-NEXT: ret i32 [[V3]] +; +Entry: + br i1 %cond, label %T, label %F + +T: + store i32 42, i32* %P1 + br label %Exit + +F: + br label %Exit + +Exit: + %V1 = load i32, i32* %P1 + %V2 = load i32, i32* %P2 + %V3 = add i32 %V1, %V2 + ret i32 %V3 +} + +define i32 @test22(i32* %P1, i32* %P2, i1 %cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test22( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: store i32 42, i32* [[P1:%.*]], align 4 +; OLDGVN-NEXT: [[V2_PRE:%.*]] = load i32, i32* [[P2:%.*]], align 4 +; OLDGVN-NEXT: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: store i32 13, i32* [[P2]], align 4 +; OLDGVN-NEXT: [[V1_PRE:%.*]] = load i32, i32* [[P1]], align 4 +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[V2:%.*]] = phi i32 [ 13, [[F]] ], [ [[V2_PRE]], [[T]] ] +; OLDGVN-NEXT: [[V1:%.*]] = phi i32 [ [[V1_PRE]], [[F]] ], [ 42, [[T]] ] +; OLDGVN-NEXT: [[V3:%.*]] = add i32 [[V1]], [[V2]] +; OLDGVN-NEXT: ret i32 [[V3]] +; +; NEWGVN-LABEL: @test22( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: store i32 42, i32* [[P1:%.*]], align 4 +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: store i32 13, i32* [[P2:%.*]], align 4 +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: [[V1:%.*]] = load i32, i32* [[P1]], align 4 +; NEWGVN-NEXT: [[V2:%.*]] = load i32, i32* [[P2]], align 4 +; NEWGVN-NEXT: [[V3:%.*]] = add i32 [[V1]], [[V2]] +; NEWGVN-NEXT: ret i32 [[V3]] +; +Entry: + br i1 %cond, label %T, label %F + +T: + store i32 42, i32* %P1 + br label %Exit + +F: + store i32 13, i32* %P2 + br label %Exit + +Exit: + %V1 = load i32, i32* %P1 + %V2 = load i32, i32* %P2 + %V3 = add i32 %V1, %V2 + ret i32 %V3 +}