diff --git a/llvm/test/Transforms/NewGVN/load_coercion_between_store_and_load.ll b/llvm/test/Transforms/NewGVN/load_coercion_between_store_and_load.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/load_coercion_between_store_and_load.ll @@ -0,0 +1,442 @@ +; 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 float @test1(i32 %V1, i32* %P) { +; OLDGVN-LABEL: @test1( +; OLDGVN-NEXT: store i32 [[V1:%.*]], i32* [[P:%.*]], align 4 +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P]] to float* +; OLDGVN-NEXT: [[TMP1:%.*]] = bitcast i32 [[V1]] to float +; OLDGVN-NEXT: ret float [[TMP1]] +; +; NEWGVN-LABEL: @test1( +; NEWGVN-NEXT: store i32 [[V1:%.*]], i32* [[P:%.*]], align 4 +; NEWGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P]] to float* +; NEWGVN-NEXT: [[V2:%.*]] = load float, float* [[P1]], align 4 +; NEWGVN-NEXT: ret float [[V2]] +; + store i32 %V1, i32* %P + %P1 = bitcast i32* %P to float* + %V2 = load float, float* %P1 + ret float %V2 +} + +define float @test2(i64* %V1, i64** %P1) { +; OLDGVN-LABEL: @test2( +; OLDGVN-NEXT: store i64* [[V1:%.*]], i64** [[P1:%.*]], align 8 +; OLDGVN-NEXT: [[P2:%.*]] = bitcast i64** [[P1]] to float* +; OLDGVN-NEXT: [[TMP1:%.*]] = ptrtoint i64* [[V1]] to i64 +; OLDGVN-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32 +; OLDGVN-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float +; OLDGVN-NEXT: ret float [[TMP3]] +; +; NEWGVN-LABEL: @test2( +; NEWGVN-NEXT: store i64* [[V1:%.*]], i64** [[P1:%.*]], align 8 +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i64** [[P1]] to float* +; NEWGVN-NEXT: [[V2:%.*]] = load float, float* [[P2]], align 4 +; NEWGVN-NEXT: ret float [[V2]] +; + store i64* %V1, i64** %P1 + %P2 = bitcast i64** %P1 to float* + %V2 = load float, float* %P2 + ret float %V2 +} + +define i8 @test3(i32 %V1, i32* %P1) { +; OLDGVN-LABEL: @test3( +; OLDGVN-NEXT: store i32 [[V1:%.*]], i32* [[P1:%.*]], align 4 +; OLDGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P1]] to i8* +; OLDGVN-NEXT: [[TMP1:%.*]] = trunc i32 [[V1]] to i8 +; OLDGVN-NEXT: ret i8 [[TMP1]] +; +; NEWGVN-LABEL: @test3( +; NEWGVN-NEXT: store i32 [[V1:%.*]], i32* [[P1:%.*]], align 4 +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P1]] to i8* +; NEWGVN-NEXT: [[V2:%.*]] = load i8, i8* [[P2]], align 1 +; NEWGVN-NEXT: ret i8 [[V2]] +; + store i32 %V1, i32* %P1 + %P2 = bitcast i32* %P1 to i8* + %V2 = load i8, i8* %P2 + ret i8 %V2 +} + +define float @test4(i64 %V1, i64* %P1) { +; OLDGVN-LABEL: @test4( +; OLDGVN-NEXT: store i64 [[V1:%.*]], i64* [[P1:%.*]], align 4 +; OLDGVN-NEXT: [[P2:%.*]] = bitcast i64* [[P1]] to float* +; OLDGVN-NEXT: [[TMP1:%.*]] = trunc i64 [[V1]] to i32 +; OLDGVN-NEXT: [[TMP2:%.*]] = bitcast i32 [[TMP1]] to float +; OLDGVN-NEXT: ret float [[TMP2]] +; +; NEWGVN-LABEL: @test4( +; NEWGVN-NEXT: store i64 [[V1:%.*]], i64* [[P1:%.*]], align 4 +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i64* [[P1]] to float* +; NEWGVN-NEXT: [[V2:%.*]] = load float, float* [[P2]], align 4 +; NEWGVN-NEXT: ret float [[V2]] +; + store i64 %V1, i64* %P1 + %P2 = bitcast i64* %P1 to float* + %V2 = load float, float* %P2 + ret float %V2 +} + +define i8 @test5(i32* %P, i8* %T) { +; GVN-LABEL: @test5( +; GVN-NEXT: [[V1:%.*]] = load i8, i8* [[T:%.*]], align 1 +; GVN-NEXT: [[P1:%.*]] = bitcast i32* [[P:%.*]] to i8* +; GVN-NEXT: [[P2:%.*]] = getelementptr i8, i8* [[P1]], i32 2 +; GVN-NEXT: store i8 [[V1]], i8* [[P2]], align 1 +; GVN-NEXT: ret i8 [[V1]] +; + %V1 = load i8, i8* %T + %P1 = bitcast i32* %P to i8* + %P2 = getelementptr i8, i8* %P1, i32 2 + store i8 %V1, i8* %P2 + %P3 = bitcast i8* %P2 to i8* + %V2 = load i8, i8* %P3 + ret i8 %V2 +} + +define i8* @test6(i64 %V1, i64* %P1) { +; OLDGVN-LABEL: @test6( +; OLDGVN-NEXT: store i64 [[V1:%.*]], i64* [[P1:%.*]], align 4 +; OLDGVN-NEXT: [[P2:%.*]] = bitcast i64* [[P1]] to i8** +; OLDGVN-NEXT: [[TMP1:%.*]] = inttoptr i64 [[V1]] to i8* +; OLDGVN-NEXT: ret i8* [[TMP1]] +; +; NEWGVN-LABEL: @test6( +; NEWGVN-NEXT: store i64 [[V1:%.*]], i64* [[P1:%.*]], align 4 +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i64* [[P1]] to i8** +; NEWGVN-NEXT: [[V2:%.*]] = load i8*, i8** [[P2]], align 8 +; NEWGVN-NEXT: ret i8* [[V2]] +; + store i64 %V1, i64* %P1 + %P2 = bitcast i64* %P1 to i8** + %V2 = load i8*, i8** %P2 + ret i8* %V2 +} + +define i32 @test7(double %V1, double* %P1) { +; OLDGVN-LABEL: @test7( +; OLDGVN-NEXT: store double [[V1:%.*]], double* [[P1:%.*]], align 8 +; OLDGVN-NEXT: [[P2:%.*]] = bitcast double* [[P1]] to i32* +; OLDGVN-NEXT: [[TMP1:%.*]] = bitcast double [[V1]] to i64 +; OLDGVN-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32 +; OLDGVN-NEXT: ret i32 [[TMP2]] +; +; NEWGVN-LABEL: @test7( +; NEWGVN-NEXT: store double [[V1:%.*]], double* [[P1:%.*]], align 8 +; NEWGVN-NEXT: [[P2:%.*]] = bitcast double* [[P1]] to i32* +; NEWGVN-NEXT: [[V2:%.*]] = load i32, i32* [[P2]], align 4 +; NEWGVN-NEXT: ret i32 [[V2]] +; + store double %V1, double* %P1 + %P2 = bitcast double* %P1 to i32* + %V2 = load i32, i32* %P2 + ret i32 %V2 +} + +define i8 @test8(i32 %V1, i32* %P1) { +; OLDGVN-LABEL: @test8( +; OLDGVN-NEXT: store i32 [[V1:%.*]], i32* [[P1:%.*]], align 4 +; OLDGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P1]] to i8* +; OLDGVN-NEXT: [[P3:%.*]] = getelementptr i8, i8* [[P2]], i32 2 +; OLDGVN-NEXT: [[TMP1:%.*]] = lshr i32 [[V1]], 16 +; OLDGVN-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i8 +; OLDGVN-NEXT: ret i8 [[TMP2]] +; +; NEWGVN-LABEL: @test8( +; NEWGVN-NEXT: store i32 [[V1:%.*]], i32* [[P1:%.*]], align 4 +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P1]] to i8* +; NEWGVN-NEXT: [[P3:%.*]] = getelementptr i8, i8* [[P2]], i32 2 +; NEWGVN-NEXT: [[V2:%.*]] = load i8, i8* [[P3]], align 1 +; NEWGVN-NEXT: ret i8 [[V2]] +; + store i32 %V1, i32* %P1 + %P2 = bitcast i32* %P1 to i8* + %P3 = getelementptr i8, i8* %P2, i32 2 + %V2 = load i8, i8* %P3 + ret i8 %V2 +} + +define double @test9(i64 %V, i64* %P1, i1 %cond) { +; Entry +; / \ +; T F +; +; OLDGVN-LABEL: @test9( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: store i64 [[V:%.*]], i64* [[P1:%.*]], align 4 +; OLDGVN-NEXT: [[P3:%.*]] = bitcast i64* [[P1]] to double* +; OLDGVN-NEXT: [[TMP0:%.*]] = bitcast i64 [[V]] to double +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: ret double [[TMP0]] +; OLDGVN: F: +; OLDGVN-NEXT: ret double [[TMP0]] +; +; NEWGVN-LABEL: @test9( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: store i64 [[V:%.*]], i64* [[P1:%.*]], align 4 +; NEWGVN-NEXT: [[P3:%.*]] = bitcast i64* [[P1]] to double* +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: [[B:%.*]] = load double, double* [[P3]], align 8 +; NEWGVN-NEXT: ret double [[B]] +; NEWGVN: F: +; NEWGVN-NEXT: [[C:%.*]] = load double, double* [[P3]], align 8 +; NEWGVN-NEXT: ret double [[C]] +; +Entry: + %A = load i64 , i64* %P1 + store i64 %V, i64* %P1 + %P3 = bitcast i64* %P1 to double* + br i1 %cond, label %T, label %F +T: + %B = load double, double* %P3 + ret double %B + +F: + %P4 = bitcast i64* %P1 to double* + %C = load double, double* %P4 + ret double %C +} + +define <{i8, float}> @test10(i32 %V0, i32* %P) { +; OLDGVN-LABEL: @test10( +; OLDGVN-NEXT: store i32 [[V0:%.*]], i32* [[P:%.*]], align 4 +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P]] to float* +; OLDGVN-NEXT: [[TMP1:%.*]] = bitcast i32 [[V0]] to float +; OLDGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P]] to i8* +; OLDGVN-NEXT: [[TMP2:%.*]] = trunc i32 [[V0]] to i8 +; OLDGVN-NEXT: [[I1:%.*]] = insertvalue <{ i8, float }> poison, i8 [[TMP2]], 0 +; OLDGVN-NEXT: [[I2:%.*]] = insertvalue <{ i8, float }> [[I1]], float [[TMP1]], 1 +; OLDGVN-NEXT: ret <{ i8, float }> [[I2]] +; +; NEWGVN-LABEL: @test10( +; NEWGVN-NEXT: store i32 [[V0:%.*]], i32* [[P:%.*]], align 4 +; NEWGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P]] to float* +; NEWGVN-NEXT: [[V1:%.*]] = load float, float* [[P1]], align 4 +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P]] to i8* +; NEWGVN-NEXT: [[V2:%.*]] = load i8, i8* [[P2]], align 1 +; NEWGVN-NEXT: [[I1:%.*]] = insertvalue <{ i8, float }> poison, i8 [[V2]], 0 +; NEWGVN-NEXT: [[I2:%.*]] = insertvalue <{ i8, float }> [[I1]], float [[V1]], 1 +; NEWGVN-NEXT: ret <{ i8, float }> [[I2]] +; + store i32 %V0, i32* %P + %P1 = bitcast i32* %P to float* + %V1 = load float, float* %P1 + %P2 = bitcast i32* %P to i8* + %V2 = load i8, i8* %P2 + %I1 = insertvalue <{i8, float}> poison, i8 %V2, 0 + %I2 = insertvalue <{i8, float}> %I1, float %V1, 1 + ret <{i8, float}> %I2 +} + +define <{i8, float}> @test11(i32 %V0, i32* %P, i1 %cond) { +; Entry +; / \ +; T F +; +; OLDGVN-LABEL: @test11( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: store i32 [[V0:%.*]], i32* [[P:%.*]], align 4 +; OLDGVN-NEXT: [[TMP0:%.*]] = trunc i32 [[V0]] to i8 +; OLDGVN-NEXT: [[TMP1:%.*]] = bitcast i32 [[V0]] to float +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P]] to float* +; OLDGVN-NEXT: [[I1:%.*]] = insertvalue <{ i8, float }> poison, float [[TMP1]], 1 +; OLDGVN-NEXT: ret <{ i8, float }> [[I1]] +; OLDGVN: F: +; OLDGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P]] to i8* +; OLDGVN-NEXT: [[I2:%.*]] = insertvalue <{ i8, float }> poison, i8 [[TMP0]], 0 +; OLDGVN-NEXT: ret <{ i8, float }> [[I2]] +; +; NEWGVN-LABEL: @test11( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: store i32 [[V0:%.*]], i32* [[P:%.*]], align 4 +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P]] to float* +; NEWGVN-NEXT: [[V1:%.*]] = load float, float* [[P1]], align 4 +; NEWGVN-NEXT: [[I1:%.*]] = insertvalue <{ i8, float }> poison, float [[V1]], 1 +; NEWGVN-NEXT: ret <{ i8, float }> [[I1]] +; NEWGVN: F: +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P]] to i8* +; NEWGVN-NEXT: [[V2:%.*]] = load i8, i8* [[P2]], align 1 +; NEWGVN-NEXT: [[I2:%.*]] = insertvalue <{ i8, float }> poison, i8 [[V2]], 0 +; NEWGVN-NEXT: ret <{ i8, float }> [[I2]] +; +Entry: + store i32 %V0, i32* %P + br i1 %cond, label %T, label %F + +T: + %P1 = bitcast i32* %P to float* + %V1 = load float, float* %P1 + %I1 = insertvalue <{i8, float}> poison, float %V1, 1 + ret <{i8, float}> %I1 + +F: + %P2 = bitcast i32* %P to i8* + %V2 = load i8, i8* %P2 + %I2 = insertvalue <{i8, float}> poison, i8 %V2, 0 + ret <{i8, float}> %I2 +} + +define <{float, float}> @test12(i32 %V0, i32* %P, i1 %cond) { +; Entry +; / \ +; T F +; +; OLDGVN-LABEL: @test12( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: store i32 [[V0:%.*]], i32* [[P:%.*]], align 4 +; OLDGVN-NEXT: [[TMP0:%.*]] = bitcast i32 [[V0]] to float +; OLDGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; OLDGVN: T: +; OLDGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P]] to float* +; OLDGVN-NEXT: [[I1:%.*]] = insertvalue <{ float, float }> poison, float [[TMP0]], 1 +; OLDGVN-NEXT: ret <{ float, float }> [[I1]] +; OLDGVN: F: +; OLDGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P]] to float* +; OLDGVN-NEXT: [[I2:%.*]] = insertvalue <{ float, float }> poison, float [[TMP0]], 0 +; OLDGVN-NEXT: ret <{ float, float }> [[I2]] +; +; NEWGVN-LABEL: @test12( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: store i32 [[V0:%.*]], i32* [[P:%.*]], align 4 +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: [[P1:%.*]] = bitcast i32* [[P]] to float* +; NEWGVN-NEXT: [[V1:%.*]] = load float, float* [[P1]], align 4 +; NEWGVN-NEXT: [[I1:%.*]] = insertvalue <{ float, float }> poison, float [[V1]], 1 +; NEWGVN-NEXT: ret <{ float, float }> [[I1]] +; NEWGVN: F: +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P]] to float* +; NEWGVN-NEXT: [[V2:%.*]] = load float, float* [[P2]], align 4 +; NEWGVN-NEXT: [[I2:%.*]] = insertvalue <{ float, float }> poison, float [[V2]], 0 +; NEWGVN-NEXT: ret <{ float, float }> [[I2]] +; +Entry: + store i32 %V0, i32* %P + br i1 %cond, label %T, label %F + +T: + %P1 = bitcast i32* %P to float* + %V1 = load float, float* %P1 + %I1 = insertvalue <{float, float}> poison, float %V1, 1 + ret <{float, float}> %I1 + +F: + %P2 = bitcast i32* %P to float* + %V2 = load float, float* %P2 + %I2 = insertvalue <{float, float}> poison, float %V2, 0 + ret <{float, float}> %I2 +} + +define i8 @test13(i32* %P1, i32 %V1) { +; OLDGVN-LABEL: @test13( +; OLDGVN-NEXT: store i32 [[V1:%.*]], i32* [[P1:%.*]], align 4 +; OLDGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P1]] to i8* +; OLDGVN-NEXT: [[TMP1:%.*]] = trunc i32 [[V1]] to i8 +; OLDGVN-NEXT: [[P3:%.*]] = bitcast i32* [[P1]] to i64* +; OLDGVN-NEXT: [[V5:%.*]] = add i8 [[TMP1]], [[TMP1]] +; OLDGVN-NEXT: ret i8 [[V5]] +; +; NEWGVN-LABEL: @test13( +; NEWGVN-NEXT: store i32 [[V1:%.*]], i32* [[P1:%.*]], align 4 +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P1]] to i8* +; NEWGVN-NEXT: [[V2:%.*]] = load i8, i8* [[P2]], align 1 +; NEWGVN-NEXT: [[P3:%.*]] = bitcast i32* [[P1]] to i64* +; NEWGVN-NEXT: [[V4:%.*]] = trunc i32 [[V1]] to i8 +; NEWGVN-NEXT: [[V5:%.*]] = add i8 [[V2]], [[V4]] +; NEWGVN-NEXT: ret i8 [[V5]] +; + store i32 %V1, i32* %P1 + %P2 = bitcast i32* %P1 to i8* + %V2 = load i8, i8* %P2 + %P3 = bitcast i32* %P1 to i64* + %V3 = load i64, i64* %P3 + %V4 = trunc i32 %V1 to i8 + %V5 = add i8 %V2, %V4 + ret i8 %V5 +} + +define i8 @test14(i32* %P1, i32 %V1) { +; OLDGVN-LABEL: @test14( +; OLDGVN-NEXT: store i32 [[V1:%.*]], i32* [[P1:%.*]], align 4 +; OLDGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P1]] to i8* +; OLDGVN-NEXT: [[TMP1:%.*]] = trunc i32 [[V1]] to i8 +; OLDGVN-NEXT: [[V5:%.*]] = add i8 [[TMP1]], [[TMP1]] +; OLDGVN-NEXT: ret i8 [[V5]] +; +; NEWGVN-LABEL: @test14( +; NEWGVN-NEXT: store i32 [[V1:%.*]], i32* [[P1:%.*]], align 4 +; NEWGVN-NEXT: [[P2:%.*]] = bitcast i32* [[P1]] to i8* +; NEWGVN-NEXT: [[V2:%.*]] = load i8, i8* [[P2]], align 1 +; NEWGVN-NEXT: [[V5:%.*]] = add i8 [[V2]], [[V2]] +; NEWGVN-NEXT: ret i8 [[V5]] +; + store i32 %V1, i32* %P1 + %P2 = bitcast i32* %P1 to i8* + %V2 = load i8, i8* %P2 + %P3 = bitcast i32* %P1 to i8* + %V3 = load i8, i8* %P3 + %V5 = add i8 %V2, %V3 + ret i8 %V5 +} + +define i16 @test15(i32* %P, i1 %Cond) { +; Entry +; / \ +; T F +; \ / +; vv +; Exit +; +; OLDGVN-LABEL: @test15( +; OLDGVN-NEXT: Entry: +; OLDGVN-NEXT: store i32 13, 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: br label [[EXIT:%.*]] +; OLDGVN: F: +; OLDGVN-NEXT: [[DOTPRE:%.*]] = bitcast i32* [[P]] to i16* +; OLDGVN-NEXT: br label [[EXIT]] +; OLDGVN: Exit: +; OLDGVN-NEXT: [[P3_PRE_PHI:%.*]] = phi i16* [ [[DOTPRE]], [[F]] ], [ [[P1]], [[T]] ] +; OLDGVN-NEXT: ret i16 13 +; +; NEWGVN-LABEL: @test15( +; NEWGVN-NEXT: Entry: +; NEWGVN-NEXT: store i32 13, i32* [[P:%.*]], align 4 +; NEWGVN-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]] +; NEWGVN: T: +; NEWGVN-NEXT: br label [[EXIT:%.*]] +; NEWGVN: F: +; NEWGVN-NEXT: br label [[EXIT]] +; NEWGVN: Exit: +; NEWGVN-NEXT: ret i16 13 +; +Entry: + store i32 13, i32* %P + br i1 %Cond, label %T, label %F + +T: + %P1 = bitcast i32* %P to i16* + %V1 = load i16, i16* %P1 + br label %Exit + +F: + %V2 = load i32, i32* %P + br label %Exit + +Exit: + %P3 = bitcast i32* %P to i16* + %V3 = load i16, i16* %P3 + ret i16 %V3 +}