diff options
Diffstat (limited to 'test/Transforms/InstCombine')
76 files changed, 3307 insertions, 51 deletions
diff --git a/test/Transforms/InstCombine/2012-07-25-LoadPart.ll b/test/Transforms/InstCombine/2012-07-25-LoadPart.ll index 73e5a66..18aab7f 100644 --- a/test/Transforms/InstCombine/2012-07-25-LoadPart.ll +++ b/test/Transforms/InstCombine/2012-07-25-LoadPart.ll @@ -1,12 +1,14 @@ -; RUN: opt < %s -instcombine -S | FileCheck %s +; RUN: opt < %s -default-data-layout="e-p:32:32:32" -instcombine -S | FileCheck %s --check-prefix=LE +; RUN: opt < %s -default-data-layout="E-p:32:32:32" -instcombine -S | FileCheck %s --check-prefix=BE ; PR13442 -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" - @test = constant [4 x i32] [i32 1, i32 2, i32 3, i32 4] define i64 @foo() { %ret = load i64* bitcast (i8* getelementptr (i8* bitcast ([4 x i32]* @test to i8*), i64 2) to i64*), align 1 ret i64 %ret - ; CHECK: ret i64 844424930263040 + ; 0x00030000_00020000 in [01 00/00 00 02 00 00 00 03 00/00 00 04 00 00 00] + ; LE: ret i64 844424930263040 + ; 0x00000200_00000300 in [00 00/00 01 00 00 00 02 00 00/00 03 00 00 00 04] + ; BE: ret i64 281474976841728 } diff --git a/test/Transforms/InstCombine/2012-08-28-udiv_ashl.ll b/test/Transforms/InstCombine/2012-08-28-udiv_ashl.ll new file mode 100644 index 0000000..4efaf8c --- /dev/null +++ b/test/Transforms/InstCombine/2012-08-28-udiv_ashl.ll @@ -0,0 +1,57 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +; rdar://12182093 + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.8.0" + +; CHECK: @udiv400 +; CHECK: udiv i32 %x, 400 +; CHECK: ret +define i32 @udiv400(i32 %x) { +entry: + %div = lshr i32 %x, 2 + %div1 = udiv i32 %div, 100 + ret i32 %div1 +} + + +; CHECK: @udiv400_no +; CHECK: ashr +; CHECK: div +; CHECK: ret +define i32 @udiv400_no(i32 %x) { +entry: + %div = ashr i32 %x, 2 + %div1 = udiv i32 %div, 100 + ret i32 %div1 +} + +; CHECK: @sdiv400_yes +; CHECK: udiv i32 %x, 400 +; CHECK: ret +define i32 @sdiv400_yes(i32 %x) { +entry: + %div = lshr i32 %x, 2 + ; The sign bits of both operands are zero (i.e. we can prove they are + ; unsigned inputs), turn this into a udiv. + ; Next, optimize this just like sdiv. + %div1 = sdiv i32 %div, 100 + ret i32 %div1 +} + + +; CHECK: @udiv_i80 +; CHECK: udiv i80 %x, 400 +; CHECK: ret +define i80 @udiv_i80(i80 %x) { + %div = lshr i80 %x, 2 + %div1 = udiv i80 %div, 100 + ret i80 %div1 +} + +define i32 @no_crash_notconst_udiv(i32 %x, i32 %notconst) { + %div = lshr i32 %x, %notconst + %div1 = udiv i32 %div, 100 + ret i32 %div1 +} diff --git a/test/Transforms/InstCombine/2012-09-17-ZeroSizedAlloca.ll b/test/Transforms/InstCombine/2012-09-17-ZeroSizedAlloca.ll new file mode 100644 index 0000000..ba025e9 --- /dev/null +++ b/test/Transforms/InstCombine/2012-09-17-ZeroSizedAlloca.ll @@ -0,0 +1,24 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +; When merging zero sized alloca check that requested alignments of the allocas +; are obeyed. + +@x = global i8* null, align 8 +@y = global i8* null, align 8 + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.8.0" + +; CHECK: @f +; CHECK-NEXT: alloca [0 x i8], align 1024 +; CHECK-NOT: alloca +; CHECK: ret void +define void @f() { + %1 = alloca [0 x i8], align 1 + %2 = alloca [0 x i8], align 1024 + %3 = getelementptr inbounds [0 x i8]* %1, i64 0, i64 0 + %4 = getelementptr inbounds [0 x i8]* %2, i64 0, i64 0 + store i8* %3, i8** @x, align 8 + store i8* %4, i8** @y, align 8 + ret void +} diff --git a/test/Transforms/InstCombine/2012-09-24-MemcpyFromGlobalCrash.ll b/test/Transforms/InstCombine/2012-09-24-MemcpyFromGlobalCrash.ll new file mode 100644 index 0000000..4cd60b4 --- /dev/null +++ b/test/Transforms/InstCombine/2012-09-24-MemcpyFromGlobalCrash.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; Check we don't crash due to lack of target data. + +@G = constant [100 x i8] zeroinitializer + +declare void @bar(i8*) +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind + +define void @test() { +; CHECK: @test +; CHECK: llvm.memcpy +; CHECK: ret void + %A = alloca [100 x i8] + %a = getelementptr inbounds [100 x i8]* %A, i64 0, i64 0 + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* getelementptr inbounds ([100 x i8]* @G, i64 0, i32 0), i64 100, i32 4, i1 false) + call void @bar(i8* %a) readonly + ret void +} diff --git a/test/Transforms/InstCombine/2012-10-25-vector-of-pointers.ll b/test/Transforms/InstCombine/2012-10-25-vector-of-pointers.ll new file mode 100644 index 0000000..20ea282 --- /dev/null +++ b/test/Transforms/InstCombine/2012-10-25-vector-of-pointers.ll @@ -0,0 +1,51 @@ +; RUN: opt < %s -instcombine -S + +; Make sure that we don't crash when optimizing the vectors of pointers. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.8.0" + +%struct.hoge = type { double*, double*, double*, double** } + +define void @widget(%struct.hoge* nocapture %arg) nounwind uwtable ssp { +bb: + %tmp = getelementptr inbounds %struct.hoge* %arg, i64 0, i32 0 + br i1 undef, label %bb1, label %bb17 + +bb1: ; preds = %bb + br i1 undef, label %bb2, label %bb3 + +bb2: ; preds = %bb1 + br label %bb17 + +bb3: ; preds = %bb1 + %tmp4 = bitcast double** %tmp to <2 x double*>* + %tmp5 = load <2 x double*>* %tmp4, align 8 + %tmp6 = ptrtoint <2 x double*> %tmp5 to <2 x i64> + %tmp7 = sub <2 x i64> zeroinitializer, %tmp6 + %tmp8 = ashr exact <2 x i64> %tmp7, <i64 3, i64 3> + %tmp9 = extractelement <2 x i64> %tmp8, i32 0 + %tmp10 = add nsw i64 undef, %tmp9 + br i1 undef, label %bb11, label %bb12 + +bb11: ; preds = %bb3 + br label %bb13 + +bb12: ; preds = %bb3 + br label %bb13 + +bb13: ; preds = %bb12, %bb11 + br i1 undef, label %bb16, label %bb14 + +bb14: ; preds = %bb13 + br i1 undef, label %bb16, label %bb15 + +bb15: ; preds = %bb14 + br label %bb16 + +bb16: ; preds = %bb15, %bb14, %bb13 + unreachable + +bb17: ; preds = %bb2, %bb + ret void +} diff --git a/test/Transforms/InstCombine/align-addr.ll b/test/Transforms/InstCombine/align-addr.ll index 27916b9..4ea1bd9 100644 --- a/test/Transforms/InstCombine/align-addr.ll +++ b/test/Transforms/InstCombine/align-addr.ll @@ -58,3 +58,19 @@ define double @test2(double* %p, double %n) nounwind { store double %n, double* %p ret double %t } + +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind + +declare void @use(i8*) + +%struct.s = type { i32, i32, i32, i32 } + +define void @test3(%struct.s* sret %a4) { +; Check that the alignment is bumped up the alignment of the sret type. +; CHECK: @test3 + %a4.cast = bitcast %struct.s* %a4 to i8* + call void @llvm.memset.p0i8.i64(i8* %a4.cast, i8 0, i64 16, i32 1, i1 false) +; CHECK: call void @llvm.memset.p0i8.i64(i8* %a4.cast, i8 0, i64 16, i32 4, i1 false) + call void @use(i8* %a4.cast) + ret void +} diff --git a/test/Transforms/InstCombine/alloca.ll b/test/Transforms/InstCombine/alloca.ll index 50e0347..68a671c 100644 --- a/test/Transforms/InstCombine/alloca.ll +++ b/test/Transforms/InstCombine/alloca.ll @@ -94,3 +94,19 @@ entry: tail call void @f(i32* %b) ret void } + +; PR14371 +%opaque_type = type opaque +%real_type = type { { i32, i32* } } + +@opaque_global = external constant %opaque_type, align 4 + +define void @test7() { +entry: + %0 = alloca %real_type, align 4 + %1 = bitcast %real_type* %0 to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %1, i8* bitcast (%opaque_type* @opaque_global to i8*), i32 8, i32 1, i1 false) + ret void +} + +declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind diff --git a/test/Transforms/InstCombine/and-fcmp.ll b/test/Transforms/InstCombine/and-fcmp.ll index 838c2f7..40c44c0 100644 --- a/test/Transforms/InstCombine/and-fcmp.ll +++ b/test/Transforms/InstCombine/and-fcmp.ll @@ -10,7 +10,7 @@ define zeroext i8 @t1(float %x, float %y) nounwind { ; CHECK: fcmp oeq float %x, %y ; CHECK-NOT: fcmp ueq float %x, %y ; CHECK-NOT: fcmp ord float %x, %y -; CHECK-NOW: and +; CHECK-NOT: and } define zeroext i8 @t2(float %x, float %y) nounwind { diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll index 56e5ca3..b4eb69d 100644 --- a/test/Transforms/InstCombine/cast.ll +++ b/test/Transforms/InstCombine/cast.ll @@ -694,3 +694,209 @@ define i1 @test67(i1 %a, i32 %b) { ; CHECK: @test67 ; CHECK: ret i1 false } + +%s = type { i32, i32, i32 } + +define %s @test68(%s *%p, i64 %i) { +; CHECK: @test68 + %o = mul i64 %i, 12 + %q = bitcast %s* %p to i8* + %pp = getelementptr inbounds i8* %q, i64 %o +; CHECK-NEXT: getelementptr %s* + %r = bitcast i8* %pp to %s* + %l = load %s* %r +; CHECK-NEXT: load %s* + ret %s %l +; CHECK-NEXT: ret %s +} + +define double @test69(double *%p, i64 %i) { +; CHECK: @test69 + %o = shl nsw i64 %i, 3 + %q = bitcast double* %p to i8* + %pp = getelementptr inbounds i8* %q, i64 %o +; CHECK-NEXT: getelementptr inbounds double* + %r = bitcast i8* %pp to double* + %l = load double* %r +; CHECK-NEXT: load double* + ret double %l +; CHECK-NEXT: ret double +} + +define %s @test70(%s *%p, i64 %i) { +; CHECK: @test70 + %o = mul nsw i64 %i, 36 +; CHECK-NEXT: mul nsw i64 %i, 3 + %q = bitcast %s* %p to i8* + %pp = getelementptr inbounds i8* %q, i64 %o +; CHECK-NEXT: getelementptr inbounds %s* + %r = bitcast i8* %pp to %s* + %l = load %s* %r +; CHECK-NEXT: load %s* + ret %s %l +; CHECK-NEXT: ret %s +} + +define double @test71(double *%p, i64 %i) { +; CHECK: @test71 + %o = shl i64 %i, 5 +; CHECK-NEXT: shl i64 %i, 2 + %q = bitcast double* %p to i8* + %pp = getelementptr i8* %q, i64 %o +; CHECK-NEXT: getelementptr double* + %r = bitcast i8* %pp to double* + %l = load double* %r +; CHECK-NEXT: load double* + ret double %l +; CHECK-NEXT: ret double +} + +define double @test72(double *%p, i32 %i) { +; CHECK: @test72 + %so = mul nsw i32 %i, 8 + %o = sext i32 %so to i64 +; CHECK-NEXT: sext i32 %i to i64 + %q = bitcast double* %p to i8* + %pp = getelementptr inbounds i8* %q, i64 %o +; CHECK-NEXT: getelementptr inbounds double* + %r = bitcast i8* %pp to double* + %l = load double* %r +; CHECK-NEXT: load double* + ret double %l +; CHECK-NEXT: ret double +} + +define double @test73(double *%p, i128 %i) { +; CHECK: @test73 + %lo = mul nsw i128 %i, 8 + %o = trunc i128 %lo to i64 +; CHECK-NEXT: trunc i128 %i to i64 + %q = bitcast double* %p to i8* + %pp = getelementptr inbounds i8* %q, i64 %o +; CHECK-NEXT: getelementptr double* + %r = bitcast i8* %pp to double* + %l = load double* %r +; CHECK-NEXT: load double* + ret double %l +; CHECK-NEXT: ret double +} + +define double @test74(double *%p, i64 %i) { +; CHECK: @test74 + %q = bitcast double* %p to i64* + %pp = getelementptr inbounds i64* %q, i64 %i +; CHECK-NEXT: getelementptr inbounds double* + %r = bitcast i64* %pp to double* + %l = load double* %r +; CHECK-NEXT: load double* + ret double %l +; CHECK-NEXT: ret double +} + +define i32* @test75(i32* %p, i32 %x) { +; CHECK: @test75 + %y = shl i32 %x, 3 +; CHECK-NEXT: shl i32 %x, 3 + %z = sext i32 %y to i64 +; CHECK-NEXT: sext i32 %y to i64 + %q = bitcast i32* %p to i8* + %r = getelementptr i8* %q, i64 %z + %s = bitcast i8* %r to i32* + ret i32* %s +} + +define %s @test76(%s *%p, i64 %i, i64 %j) { +; CHECK: @test76 + %o = mul i64 %i, 12 + %o2 = mul nsw i64 %o, %j +; CHECK-NEXT: %o2 = mul i64 %i, %j + %q = bitcast %s* %p to i8* + %pp = getelementptr inbounds i8* %q, i64 %o2 +; CHECK-NEXT: getelementptr %s* %p, i64 %o2 + %r = bitcast i8* %pp to %s* + %l = load %s* %r +; CHECK-NEXT: load %s* + ret %s %l +; CHECK-NEXT: ret %s +} + +define %s @test77(%s *%p, i64 %i, i64 %j) { +; CHECK: @test77 + %o = mul nsw i64 %i, 36 + %o2 = mul nsw i64 %o, %j +; CHECK-NEXT: %o = mul nsw i64 %i, 3 +; CHECK-NEXT: %o2 = mul nsw i64 %o, %j + %q = bitcast %s* %p to i8* + %pp = getelementptr inbounds i8* %q, i64 %o2 +; CHECK-NEXT: getelementptr inbounds %s* %p, i64 %o2 + %r = bitcast i8* %pp to %s* + %l = load %s* %r +; CHECK-NEXT: load %s* + ret %s %l +; CHECK-NEXT: ret %s +} + +define %s @test78(%s *%p, i64 %i, i64 %j, i32 %k, i32 %l, i128 %m, i128 %n) { +; CHECK: @test78 + %a = mul nsw i32 %k, 36 +; CHECK-NEXT: mul nsw i32 %k, 3 + %b = mul nsw i32 %a, %l +; CHECK-NEXT: mul nsw i32 %a, %l + %c = sext i32 %b to i128 +; CHECK-NEXT: sext i32 %b to i128 + %d = mul nsw i128 %c, %m +; CHECK-NEXT: mul nsw i128 %c, %m + %e = mul i128 %d, %n +; CHECK-NEXT: mul i128 %d, %n + %f = trunc i128 %e to i64 +; CHECK-NEXT: trunc i128 %e to i64 + %g = mul nsw i64 %f, %i +; CHECK-NEXT: mul i64 %f, %i + %h = mul nsw i64 %g, %j +; CHECK-NEXT: mul i64 %g, %j + %q = bitcast %s* %p to i8* + %pp = getelementptr inbounds i8* %q, i64 %h +; CHECK-NEXT: getelementptr %s* %p, i64 %h + %r = bitcast i8* %pp to %s* + %load = load %s* %r +; CHECK-NEXT: load %s* + ret %s %load +; CHECK-NEXT: ret %s +} + +define %s @test79(%s *%p, i64 %i, i32 %j) { +; CHECK: @test79 + %a = mul nsw i64 %i, 36 +; CHECK: mul nsw i64 %i, 36 + %b = trunc i64 %a to i32 + %c = mul i32 %b, %j + %q = bitcast %s* %p to i8* +; CHECK: bitcast + %pp = getelementptr inbounds i8* %q, i32 %c + %r = bitcast i8* %pp to %s* + %l = load %s* %r + ret %s %l +} + +define double @test80([100 x double]* %p, i32 %i) { +; CHECK: @test80 + %tmp = mul nsw i32 %i, 8 +; CHECK-NEXT: sext i32 %i to i64 + %q = bitcast [100 x double]* %p to i8* + %pp = getelementptr i8* %q, i32 %tmp +; CHECK-NEXT: getelementptr [100 x double]* + %r = bitcast i8* %pp to double* + %l = load double* %r +; CHECK-NEXT: load double* + ret double %l +; CHECK-NEXT: ret double +} + +define double @test81(double *%p, float %f) { + %i = fptosi float %f to i64 + %q = bitcast double* %p to i8* + %pp = getelementptr i8* %q, i64 %i + %r = bitcast i8* %pp to double* + %l = load double* %r + ret double %l +} diff --git a/test/Transforms/InstCombine/disable-simplify-libcalls.ll b/test/Transforms/InstCombine/disable-simplify-libcalls.ll new file mode 100644 index 0000000..d81e9ae --- /dev/null +++ b/test/Transforms/InstCombine/disable-simplify-libcalls.ll @@ -0,0 +1,236 @@ +; Test that -disable-simplify-libcalls is wired up correctly. +; +; RUN: opt < %s -instcombine -disable-simplify-libcalls -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +@.str = constant [1 x i8] zeroinitializer, align 1 +@.str1 = constant [13 x i8] c"hello, world\00", align 1 +@.str2 = constant [4 x i8] c"foo\00", align 1 +@.str3 = constant [4 x i8] c"bar\00", align 1 +@.str4 = constant [6 x i8] c"123.4\00", align 1 +@.str5 = constant [5 x i8] c"1234\00", align 1 +@empty = constant [1 x i8] c"\00", align 1 + +declare double @ceil(double) +declare double @copysign(double, double) +declare double @cos(double) +declare double @fabs(double) +declare double @floor(double) +declare i8* @strcat(i8*, i8*) +declare i8* @strncat(i8*, i8*, i32) +declare i8* @strchr(i8*, i32) +declare i8* @strrchr(i8*, i32) +declare i32 @strcmp(i8*, i8*) +declare i32 @strncmp(i8*, i8*, i64) +declare i8* @strcpy(i8*, i8*) +declare i8* @stpcpy(i8*, i8*) +declare i8* @strncpy(i8*, i8*, i64) +declare i64 @strlen(i8*) +declare i8* @strpbrk(i8*, i8*) +declare i64 @strspn(i8*, i8*) +declare double @strtod(i8*, i8**) +declare float @strtof(i8*, i8**) +declare x86_fp80 @strtold(i8*, i8**) +declare i64 @strtol(i8*, i8**, i32) +declare i64 @strtoll(i8*, i8**, i32) +declare i64 @strtoul(i8*, i8**, i32) +declare i64 @strtoull(i8*, i8**, i32) +declare i64 @strcspn(i8*, i8*) + +define double @t1(double %x) { +; CHECK: @t1 + %ret = call double @ceil(double %x) + ret double %ret +; CHECK: call double @ceil +} + +define double @t2(double %x, double %y) { +; CHECK: @t2 + %ret = call double @copysign(double %x, double %y) + ret double %ret +; CHECK: call double @copysign +} + +define double @t3(double %x) { +; CHECK: @t3 + %call = call double @cos(double %x) + ret double %call +; CHECK: call double @cos +} + +define double @t4(double %x) { +; CHECK: @t4 + %ret = call double @fabs(double %x) + ret double %ret +; CHECK: call double @fabs +} + +define double @t5(double %x) { +; CHECK: @t5 + %ret = call double @floor(double %x) + ret double %ret +; CHECK: call double @floor +} + +define i8* @t6(i8* %x) { +; CHECK: @t6 + %empty = getelementptr [1 x i8]* @empty, i32 0, i32 0 + %ret = call i8* @strcat(i8* %x, i8* %empty) + ret i8* %ret +; CHECK: call i8* @strcat +} + +define i8* @t7(i8* %x) { +; CHECK: @t7 + %empty = getelementptr [1 x i8]* @empty, i32 0, i32 0 + %ret = call i8* @strncat(i8* %x, i8* %empty, i32 1) + ret i8* %ret +; CHECK: call i8* @strncat +} + +define i8* @t8() { +; CHECK: @t8 + %x = getelementptr inbounds [13 x i8]* @.str1, i32 0, i32 0 + %ret = call i8* @strchr(i8* %x, i32 119) + ret i8* %ret +; CHECK: call i8* @strchr +} + +define i8* @t9() { +; CHECK: @t9 + %x = getelementptr inbounds [13 x i8]* @.str1, i32 0, i32 0 + %ret = call i8* @strrchr(i8* %x, i32 119) + ret i8* %ret +; CHECK: call i8* @strrchr +} + +define i32 @t10() { +; CHECK: @t10 + %x = getelementptr inbounds [4 x i8]* @.str2, i32 0, i32 0 + %y = getelementptr inbounds [4 x i8]* @.str3, i32 0, i32 0 + %ret = call i32 @strcmp(i8* %x, i8* %y) + ret i32 %ret +; CHECK: call i32 @strcmp +} + +define i32 @t11() { +; CHECK: @t11 + %x = getelementptr inbounds [4 x i8]* @.str2, i32 0, i32 0 + %y = getelementptr inbounds [4 x i8]* @.str3, i32 0, i32 0 + %ret = call i32 @strncmp(i8* %x, i8* %y, i64 3) + ret i32 %ret +; CHECK: call i32 @strncmp +} + +define i8* @t12(i8* %x) { +; CHECK: @t12 + %y = getelementptr inbounds [4 x i8]* @.str2, i32 0, i32 0 + %ret = call i8* @strcpy(i8* %x, i8* %y) + ret i8* %ret +; CHECK: call i8* @strcpy +} + +define i8* @t13(i8* %x) { +; CHECK: @t13 + %y = getelementptr inbounds [4 x i8]* @.str2, i32 0, i32 0 + %ret = call i8* @stpcpy(i8* %x, i8* %y) + ret i8* %ret +; CHECK: call i8* @stpcpy +} + +define i8* @t14(i8* %x) { +; CHECK: @t14 + %y = getelementptr inbounds [4 x i8]* @.str2, i32 0, i32 0 + %ret = call i8* @strncpy(i8* %x, i8* %y, i64 3) + ret i8* %ret +; CHECK: call i8* @strncpy +} + +define i64 @t15() { +; CHECK: @t15 + %x = getelementptr inbounds [4 x i8]* @.str2, i32 0, i32 0 + %ret = call i64 @strlen(i8* %x) + ret i64 %ret +; CHECK: call i64 @strlen +} + +define i8* @t16(i8* %x) { +; CHECK: @t16 + %y = getelementptr inbounds [1 x i8]* @.str, i32 0, i32 0 + %ret = call i8* @strpbrk(i8* %x, i8* %y) + ret i8* %ret +; CHECK: call i8* @strpbrk +} + +define i64 @t17(i8* %x) { +; CHECK: @t17 + %y = getelementptr inbounds [1 x i8]* @.str, i32 0, i32 0 + %ret = call i64 @strspn(i8* %x, i8* %y) + ret i64 %ret +; CHECK: call i64 @strspn +} + +define double @t18(i8** %y) { +; CHECK: @t18 + %x = getelementptr inbounds [6 x i8]* @.str4, i64 0, i64 0 + %ret = call double @strtod(i8* %x, i8** %y) + ret double %ret +; CHECK: call double @strtod +} + +define float @t19(i8** %y) { +; CHECK: @t19 + %x = getelementptr inbounds [6 x i8]* @.str4, i64 0, i64 0 + %ret = call float @strtof(i8* %x, i8** %y) + ret float %ret +; CHECK: call float @strtof +} + +define x86_fp80 @t20(i8** %y) { +; CHECK: @t20 + %x = getelementptr inbounds [6 x i8]* @.str4, i64 0, i64 0 + %ret = call x86_fp80 @strtold(i8* %x, i8** %y) + ret x86_fp80 %ret +; CHECK: call x86_fp80 @strtold +} + +define i64 @t21(i8** %y) { +; CHECK: @t21 + %x = getelementptr inbounds [5 x i8]* @.str5, i64 0, i64 0 + %ret = call i64 @strtol(i8* %x, i8** %y, i32 10) + ret i64 %ret +; CHECK: call i64 @strtol +} + +define i64 @t22(i8** %y) { +; CHECK: @t22 + %x = getelementptr inbounds [5 x i8]* @.str5, i64 0, i64 0 + %ret = call i64 @strtoll(i8* %x, i8** %y, i32 10) + ret i64 %ret +; CHECK: call i64 @strtoll +} + +define i64 @t23(i8** %y) { +; CHECK: @t23 + %x = getelementptr inbounds [5 x i8]* @.str5, i64 0, i64 0 + %ret = call i64 @strtoul(i8* %x, i8** %y, i32 10) + ret i64 %ret +; CHECK: call i64 @strtoul +} + +define i64 @t24(i8** %y) { +; CHECK: @t24 + %x = getelementptr inbounds [5 x i8]* @.str5, i64 0, i64 0 + %ret = call i64 @strtoull(i8* %x, i8** %y, i32 10) + ret i64 %ret +; CHECK: call i64 @strtoull +} + +define i64 @t25(i8* %y) { +; CHECK: @t25 + %x = getelementptr [1 x i8]* @empty, i32 0, i32 0 + %ret = call i64 @strcspn(i8* %x, i8* %y) + ret i64 %ret +; CHECK: call i64 @strcspn +} diff --git a/test/Transforms/InstCombine/div-shift.ll b/test/Transforms/InstCombine/div-shift.ll index a07f3ea..e0372eb 100644 --- a/test/Transforms/InstCombine/div-shift.ll +++ b/test/Transforms/InstCombine/div-shift.ll @@ -21,3 +21,17 @@ define i64 @t2(i64 %x, i32 %y) nounwind { %3 = udiv i64 %x, %2 ret i64 %3 } + +; PR13250 +define i64 @t3(i64 %x, i32 %y) nounwind { +; CHECK: t3 +; CHECK-NOT: udiv +; CHECK-NEXT: %1 = add i32 %y, 2 +; CHECK-NEXT: %2 = zext i32 %1 to i64 +; CHECK-NEXT: %3 = lshr i64 %x, %2 +; CHECK-NEXT: ret i64 %3 + %1 = shl i32 4, %y + %2 = zext i32 %1 to i64 + %3 = udiv i64 %x, %2 + ret i64 %3 +} diff --git a/test/Transforms/InstCombine/fcmp.ll b/test/Transforms/InstCombine/fcmp.ll index d08cbf5..376fa07 100644 --- a/test/Transforms/InstCombine/fcmp.ll +++ b/test/Transforms/InstCombine/fcmp.ll @@ -54,9 +54,8 @@ define i1 @test7(float %x) nounwind readnone ssp noredzone { %ext = fpext float %x to ppc_fp128 %cmp = fcmp ogt ppc_fp128 %ext, 0xM00000000000000000000000000000000 ret i1 %cmp -; Can't convert ppc_fp128 ; CHECK: @test7 -; CHECK-NEXT: fpext float %x to ppc_fp128 +; CHECK-NEXT: fcmp ogt float %x, 0.000000e+00 } define float @test8(float %x) nounwind readnone optsize ssp { @@ -69,3 +68,93 @@ define float @test8(float %x) nounwind readnone optsize ssp { ; CHECK: @test8 ; CHECK-NEXT: fcmp olt float %x, 0.000000e+00 } + +declare double @fabs(double) nounwind readnone + +define i32 @test9(double %a) nounwind { + %call = tail call double @fabs(double %a) nounwind + %cmp = fcmp olt double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK: @test9 +; CHECK-NOT: fabs +; CHECK: ret i32 0 +} + +define i32 @test10(double %a) nounwind { + %call = tail call double @fabs(double %a) nounwind + %cmp = fcmp ole double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK: @test10 +; CHECK-NOT: fabs +; CHECK: fcmp oeq double %a, 0.000000e+00 +} + +define i32 @test11(double %a) nounwind { + %call = tail call double @fabs(double %a) nounwind + %cmp = fcmp ogt double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK: @test11 +; CHECK-NOT: fabs +; CHECK: fcmp one double %a, 0.000000e+00 +} + +define i32 @test12(double %a) nounwind { + %call = tail call double @fabs(double %a) nounwind + %cmp = fcmp oge double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK: @test12 +; CHECK-NOT: fabs +; CHECK: fcmp ord double %a, 0.000000e+00 +} + +define i32 @test13(double %a) nounwind { + %call = tail call double @fabs(double %a) nounwind + %cmp = fcmp une double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK: @test13 +; CHECK-NOT: fabs +; CHECK: fcmp une double %a, 0.000000e+00 +} + +define i32 @test14(double %a) nounwind { + %call = tail call double @fabs(double %a) nounwind + %cmp = fcmp oeq double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK: @test14 +; CHECK-NOT: fabs +; CHECK: fcmp oeq double %a, 0.000000e+00 +} + +define i32 @test15(double %a) nounwind { + %call = tail call double @fabs(double %a) nounwind + %cmp = fcmp one double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK: @test15 +; CHECK-NOT: fabs +; CHECK: fcmp one double %a, 0.000000e+00 +} + +define i32 @test16(double %a) nounwind { + %call = tail call double @fabs(double %a) nounwind + %cmp = fcmp ueq double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK: @test16 +; CHECK-NOT: fabs +; CHECK: fcmp ueq double %a, 0.000000e+00 +} + +; Don't crash. +define i32 @test17(double %a, double (double)* %p) nounwind { + %call = tail call double %p(double %a) nounwind + %cmp = fcmp ueq double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +} diff --git a/test/Transforms/InstCombine/fold-vector-select.ll b/test/Transforms/InstCombine/fold-vector-select.ll index 3f22522..2cb970b 100644 --- a/test/Transforms/InstCombine/fold-vector-select.ll +++ b/test/Transforms/InstCombine/fold-vector-select.ll @@ -1,13 +1,148 @@ ; RUN: opt < %s -instcombine -S | not grep select -define void @foo(<4 x i32> *%A, <4 x i32> *%B, <4 x i32> *%C, <4 x i32> *%D) { - %r = select <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> <i32 1, i32 2, i32 3, i32 4>, <4 x i32> zeroinitializer - %g = select <4 x i1> <i1 false, i1 false, i1 false, i1 false>, <4 x i32> zeroinitializer, <4 x i32> <i32 3, i32 6, i32 9, i32 1> - %b = select <4 x i1> <i1 false, i1 true, i1 false, i1 true>, <4 x i32> zeroinitializer, <4 x i32> <i32 7, i32 1, i32 4, i32 9> - %a = select <4 x i1> zeroinitializer, <4 x i32> zeroinitializer, <4 x i32> <i32 3, i32 2, i32 8, i32 5> - store <4 x i32> %r, <4 x i32>* %A - store <4 x i32> %g, <4 x i32>* %B - store <4 x i32> %b, <4 x i32>* %C - store <4 x i32> %a, <4 x i32>* %D +define void @foo(<4 x i32> *%A, <4 x i32> *%B, <4 x i32> *%C, <4 x i32> *%D, + <4 x i32> *%E, <4 x i32> *%F, <4 x i32> *%G, <4 x i32> *%H, + <4 x i32> *%I, <4 x i32> *%J, <4 x i32> *%K, <4 x i32> *%L, + <4 x i32> *%M, <4 x i32> *%N, <4 x i32> *%O, <4 x i32> *%P, + <4 x i32> *%Q, <4 x i32> *%R, <4 x i32> *%S, <4 x i32> *%T, + <4 x i32> *%U, <4 x i32> *%V, <4 x i32> *%W, <4 x i32> *%X, + <4 x i32> *%Y, <4 x i32> *%Z, <4 x i32> *%BA, <4 x i32> *%BB, + <4 x i32> *%BC, <4 x i32> *%BD, <4 x i32> *%BE, <4 x i32> *%BF, + <4 x i32> *%BG, <4 x i32> *%BH, <4 x i32> *%BI, <4 x i32> *%BJ, + <4 x i32> *%BK, <4 x i32> *%BL, <4 x i32> *%BM, <4 x i32> *%BN, + <4 x i32> *%BO, <4 x i32> *%BP, <4 x i32> *%BQ, <4 x i32> *%BR, + <4 x i32> *%BS, <4 x i32> *%BT, <4 x i32> *%BU, <4 x i32> *%BV, + <4 x i32> *%BW, <4 x i32> *%BX, <4 x i32> *%BY, <4 x i32> *%BZ, + <4 x i32> *%CA, <4 x i32> *%CB, <4 x i32> *%CC, <4 x i32> *%CD, + <4 x i32> *%CE, <4 x i32> *%CF, <4 x i32> *%CG, <4 x i32> *%CH, + <4 x i32> *%CI, <4 x i32> *%CJ, <4 x i32> *%CK, <4 x i32> *%CL) { + %a = select <4 x i1> <i1 false, i1 false, i1 false, i1 false>, <4 x i32> zeroinitializer, <4 x i32> <i32 9, i32 87, i32 57, i32 8> + %b = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x i32> zeroinitializer, <4 x i32> <i32 44, i32 99, i32 49, i32 29> + %c = select <4 x i1> <i1 false, i1 true, i1 false, i1 false>, <4 x i32> zeroinitializer, <4 x i32> <i32 15, i32 18, i32 53, i32 84> + %d = select <4 x i1> <i1 true, i1 true, i1 false, i1 false>, <4 x i32> zeroinitializer, <4 x i32> <i32 29, i32 82, i32 45, i32 16> + %e = select <4 x i1> <i1 false, i1 false, i1 true, i1 false>, <4 x i32> zeroinitializer, <4 x i32> <i32 11, i32 15, i32 32, i32 99> + %f = select <4 x i1> <i1 true, i1 false, i1 true, i1 false>, <4 x i32> zeroinitializer, <4 x i32> <i32 19, i32 86, i32 29, i32 33> + %g = select <4 x i1> <i1 false, i1 true, i1 true, i1 false>, <4 x i32> zeroinitializer, <4 x i32> <i32 44, i32 10, i32 26, i32 45> + %h = select <4 x i1> <i1 true, i1 true, i1 true, i1 false>, <4 x i32> zeroinitializer, <4 x i32> <i32 88, i32 70, i32 90, i32 48> + %i = select <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x i32> zeroinitializer, <4 x i32> <i32 30, i32 53, i32 42, i32 12> + %j = select <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x i32> zeroinitializer, <4 x i32> <i32 46, i32 24, i32 93, i32 26> + %k = select <4 x i1> <i1 false, i1 true, i1 false, i1 true>, <4 x i32> zeroinitializer, <4 x i32> <i32 33, i32 99, i32 15, i32 57> + %l = select <4 x i1> <i1 true, i1 true, i1 false, i1 true>, <4 x i32> zeroinitializer, <4 x i32> <i32 51, i32 60, i32 60, i32 50> + %m = select <4 x i1> <i1 false, i1 false, i1 true, i1 true>, <4 x i32> zeroinitializer, <4 x i32> <i32 50, i32 12, i32 7, i32 45> + %n = select <4 x i1> <i1 true, i1 false, i1 true, i1 true>, <4 x i32> zeroinitializer, <4 x i32> <i32 15, i32 65, i32 36, i32 36> + %o = select <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x i32> zeroinitializer, <4 x i32> <i32 54, i32 0, i32 17, i32 78> + %p = select <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> zeroinitializer, <4 x i32> <i32 56, i32 13, i32 64, i32 48> + %q = select <4 x i1> <i1 false, i1 false, i1 false, i1 false>, <4 x i32> <i32 52, i32 69, i32 88, i32 11>, <4 x i32> zeroinitializer + %r = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x i32> <i32 5, i32 87, i32 68, i32 14>, <4 x i32> zeroinitializer + %s = select <4 x i1> <i1 false, i1 true, i1 false, i1 false>, <4 x i32> <i32 47, i32 17, i32 66, i32 63>, <4 x i32> zeroinitializer + %t = select <4 x i1> <i1 true, i1 true, i1 false, i1 false>, <4 x i32> <i32 64, i32 25, i32 73, i32 81>, <4 x i32> zeroinitializer + %u = select <4 x i1> <i1 false, i1 false, i1 true, i1 false>, <4 x i32> <i32 51, i32 41, i32 61, i32 63>, <4 x i32> zeroinitializer + %v = select <4 x i1> <i1 true, i1 false, i1 true, i1 false>, <4 x i32> <i32 39, i32 59, i32 17, i32 0>, <4 x i32> zeroinitializer + %w = select <4 x i1> <i1 false, i1 true, i1 true, i1 false>, <4 x i32> <i32 91, i32 99, i32 97, i32 29>, <4 x i32> zeroinitializer + %x = select <4 x i1> <i1 true, i1 true, i1 true, i1 false>, <4 x i32> <i32 89, i32 45, i32 89, i32 10>, <4 x i32> zeroinitializer + %y = select <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x i32> <i32 25, i32 70, i32 21, i32 27>, <4 x i32> zeroinitializer + %z = select <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x i32> <i32 40, i32 12, i32 27, i32 88>, <4 x i32> zeroinitializer + %ba = select <4 x i1> <i1 false, i1 true, i1 false, i1 true>, <4 x i32> <i32 36, i32 35, i32 90, i32 23>, <4 x i32> zeroinitializer + %bb = select <4 x i1> <i1 true, i1 true, i1 false, i1 true>, <4 x i32> <i32 83, i32 3, i32 64, i32 82>, <4 x i32> zeroinitializer + %bc = select <4 x i1> <i1 false, i1 false, i1 true, i1 true>, <4 x i32> <i32 15, i32 72, i32 2, i32 54>, <4 x i32> zeroinitializer + %bd = select <4 x i1> <i1 true, i1 false, i1 true, i1 true>, <4 x i32> <i32 32, i32 47, i32 100, i32 84>, <4 x i32> zeroinitializer + %be = select <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x i32> <i32 92, i32 57, i32 82, i32 1>, <4 x i32> zeroinitializer + %bf = select <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> <i32 42, i32 14, i32 22, i32 89>, <4 x i32> zeroinitializer + %bg = select <4 x i1> <i1 false, i1 false, i1 false, i1 false>, <4 x i32> <i32 33, i32 10, i32 67, i32 66>, <4 x i32> <i32 42, i32 91, i32 47, i32 40> + %bh = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x i32> <i32 8, i32 13, i32 48, i32 0>, <4 x i32> <i32 84, i32 66, i32 87, i32 84> + %bi = select <4 x i1> <i1 false, i1 true, i1 false, i1 false>, <4 x i32> <i32 85, i32 96, i32 1, i32 94>, <4 x i32> <i32 54, i32 57, i32 7, i32 92> + %bj = select <4 x i1> <i1 true, i1 true, i1 false, i1 false>, <4 x i32> <i32 55, i32 21, i32 92, i32 68>, <4 x i32> <i32 51, i32 61, i32 62, i32 39> + %bk = select <4 x i1> <i1 false, i1 false, i1 true, i1 false>, <4 x i32> <i32 42, i32 18, i32 77, i32 74>, <4 x i32> <i32 82, i32 33, i32 30, i32 7> + %bl = select <4 x i1> <i1 true, i1 false, i1 true, i1 false>, <4 x i32> <i32 80, i32 92, i32 61, i32 84>, <4 x i32> <i32 43, i32 89, i32 92, i32 6> + %bm = select <4 x i1> <i1 false, i1 true, i1 true, i1 false>, <4 x i32> <i32 49, i32 14, i32 62, i32 62>, <4 x i32> <i32 35, i32 33, i32 92, i32 59> + %bn = select <4 x i1> <i1 true, i1 true, i1 true, i1 false>, <4 x i32> <i32 3, i32 97, i32 49, i32 18>, <4 x i32> <i32 56, i32 64, i32 19, i32 75> + %bo = select <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x i32> <i32 91, i32 57, i32 0, i32 1>, <4 x i32> <i32 43, i32 63, i32 64, i32 11> + %bp = select <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x i32> <i32 41, i32 65, i32 18, i32 11>, <4 x i32> <i32 86, i32 26, i32 31, i32 3> + %bq = select <4 x i1> <i1 false, i1 true, i1 false, i1 true>, <4 x i32> <i32 31, i32 46, i32 32, i32 68>, <4 x i32> <i32 100, i32 59, i32 62, i32 6> + %br = select <4 x i1> <i1 true, i1 true, i1 false, i1 true>, <4 x i32> <i32 76, i32 67, i32 87, i32 7>, <4 x i32> <i32 63, i32 48, i32 97, i32 24> + %bs = select <4 x i1> <i1 false, i1 false, i1 true, i1 true>, <4 x i32> <i32 83, i32 89, i32 19, i32 4>, <4 x i32> <i32 21, i32 2, i32 40, i32 21> + %bt = select <4 x i1> <i1 true, i1 false, i1 true, i1 true>, <4 x i32> <i32 45, i32 76, i32 81, i32 100>, <4 x i32> <i32 65, i32 26, i32 100, i32 46> + %bu = select <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x i32> <i32 16, i32 75, i32 31, i32 17>, <4 x i32> <i32 37, i32 66, i32 86, i32 65> + %bv = select <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> <i32 13, i32 25, i32 43, i32 59>, <4 x i32> <i32 82, i32 78, i32 60, i32 52> + %bw = select <4 x i1> <i1 false, i1 false, i1 false, i1 false>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %bx = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %by = select <4 x i1> <i1 false, i1 true, i1 false, i1 false>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %bz = select <4 x i1> <i1 true, i1 true, i1 false, i1 false>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %ca = select <4 x i1> <i1 false, i1 false, i1 true, i1 false>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %cb = select <4 x i1> <i1 true, i1 false, i1 true, i1 false>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %cc = select <4 x i1> <i1 false, i1 true, i1 true, i1 false>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %cd = select <4 x i1> <i1 true, i1 true, i1 true, i1 false>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %ce = select <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %cf = select <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %cg = select <4 x i1> <i1 false, i1 true, i1 false, i1 true>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %ch = select <4 x i1> <i1 true, i1 true, i1 false, i1 true>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %ci = select <4 x i1> <i1 false, i1 false, i1 true, i1 true>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %cj = select <4 x i1> <i1 true, i1 false, i1 true, i1 true>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %ck = select <4 x i1> <i1 false, i1 true, i1 true, i1 true>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + %cl = select <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + store <4 x i32> %a, <4 x i32>* %A + store <4 x i32> %b, <4 x i32>* %B + store <4 x i32> %c, <4 x i32>* %C + store <4 x i32> %d, <4 x i32>* %D + store <4 x i32> %e, <4 x i32>* %E + store <4 x i32> %f, <4 x i32>* %F + store <4 x i32> %g, <4 x i32>* %G + store <4 x i32> %h, <4 x i32>* %H + store <4 x i32> %i, <4 x i32>* %I + store <4 x i32> %j, <4 x i32>* %J + store <4 x i32> %k, <4 x i32>* %K + store <4 x i32> %l, <4 x i32>* %L + store <4 x i32> %m, <4 x i32>* %M + store <4 x i32> %n, <4 x i32>* %N + store <4 x i32> %o, <4 x i32>* %O + store <4 x i32> %p, <4 x i32>* %P + store <4 x i32> %q, <4 x i32>* %Q + store <4 x i32> %r, <4 x i32>* %R + store <4 x i32> %s, <4 x i32>* %S + store <4 x i32> %t, <4 x i32>* %T + store <4 x i32> %u, <4 x i32>* %U + store <4 x i32> %v, <4 x i32>* %V + store <4 x i32> %w, <4 x i32>* %W + store <4 x i32> %x, <4 x i32>* %X + store <4 x i32> %y, <4 x i32>* %Y + store <4 x i32> %z, <4 x i32>* %Z + store <4 x i32> %ba, <4 x i32>* %BA + store <4 x i32> %bb, <4 x i32>* %BB + store <4 x i32> %bc, <4 x i32>* %BC + store <4 x i32> %bd, <4 x i32>* %BD + store <4 x i32> %be, <4 x i32>* %BE + store <4 x i32> %bf, <4 x i32>* %BF + store <4 x i32> %bg, <4 x i32>* %BG + store <4 x i32> %bh, <4 x i32>* %BH + store <4 x i32> %bi, <4 x i32>* %BI + store <4 x i32> %bj, <4 x i32>* %BJ + store <4 x i32> %bk, <4 x i32>* %BK + store <4 x i32> %bl, <4 x i32>* %BL + store <4 x i32> %bm, <4 x i32>* %BM + store <4 x i32> %bn, <4 x i32>* %BN + store <4 x i32> %bo, <4 x i32>* %BO + store <4 x i32> %bp, <4 x i32>* %BP + store <4 x i32> %bq, <4 x i32>* %BQ + store <4 x i32> %br, <4 x i32>* %BR + store <4 x i32> %bs, <4 x i32>* %BS + store <4 x i32> %bt, <4 x i32>* %BT + store <4 x i32> %bu, <4 x i32>* %BU + store <4 x i32> %bv, <4 x i32>* %BV + store <4 x i32> %bw, <4 x i32>* %BW + store <4 x i32> %bx, <4 x i32>* %BX + store <4 x i32> %by, <4 x i32>* %BY + store <4 x i32> %bz, <4 x i32>* %BZ + store <4 x i32> %ca, <4 x i32>* %CA + store <4 x i32> %cb, <4 x i32>* %CB + store <4 x i32> %cc, <4 x i32>* %CC + store <4 x i32> %cd, <4 x i32>* %CD + store <4 x i32> %ce, <4 x i32>* %CE + store <4 x i32> %cf, <4 x i32>* %CF + store <4 x i32> %cg, <4 x i32>* %CG + store <4 x i32> %ch, <4 x i32>* %CH + store <4 x i32> %ci, <4 x i32>* %CI + store <4 x i32> %cj, <4 x i32>* %CJ + store <4 x i32> %ck, <4 x i32>* %CK + store <4 x i32> %cl, <4 x i32>* %CL ret void } diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index eaff87d..8e064a4 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -659,3 +659,21 @@ define i1 @test64(i8 %a, i32 %b) nounwind { ; CHECK-NEXT: %c = icmp eq i8 %1, %a ; CHECK-NEXT: ret i1 %c } + +define i1 @test65(i64 %A, i64 %B) { + %s1 = add i64 %A, %B + %s2 = add i64 %A, %B + %cmp = icmp eq i64 %s1, %s2 +; CHECK: @test65 +; CHECK-NEXT: ret i1 true + ret i1 %cmp +} + +define i1 @test66(i64 %A, i64 %B) { + %s1 = add i64 %A, %B + %s2 = add i64 %B, %A + %cmp = icmp eq i64 %s1, %s2 +; CHECK: @test66 +; CHECK-NEXT: ret i1 true + ret i1 %cmp +} diff --git a/test/Transforms/InstCombine/memcmp-1.ll b/test/Transforms/InstCombine/memcmp-1.ll new file mode 100644 index 0000000..4238c5f --- /dev/null +++ b/test/Transforms/InstCombine/memcmp-1.ll @@ -0,0 +1,72 @@ +; Test that the memcmp library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@foo = constant [4 x i8] c"foo\00" +@hel = constant [4 x i8] c"hel\00" +@hello_u = constant [8 x i8] c"hello_u\00" + +declare i32 @memcmp(i8*, i8*, i32) + +; Check memcmp(mem, mem, size) -> 0. + +define i32 @test_simplify1(i8* %mem, i32 %size) { +; CHECK: @test_simplify1 + %ret = call i32 @memcmp(i8* %mem, i8* %mem, i32 %size) + ret i32 %ret +; CHECK: ret i32 0 +} + +; Check memcmp(mem1, mem2, 0) -> 0. + +define i32 @test_simplify2(i8* %mem1, i8* %mem2) { +; CHECK: @test_simplify2 + %ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 0) + ret i32 %ret +; CHECK: ret i32 0 +} + +;; Check memcmp(mem1, mem2, 1) -> *(unsigned char*)mem1 - *(unsigned char*)mem2. + +define i32 @test_simplify3(i8* %mem1, i8* %mem2) { +; CHECK: @test_simplify3 + %ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 1) +; CHECK: [[LOAD1:%[a-z]+]] = load i8* %mem1, align 1 +; CHECK: [[ZEXT1:%[a-z]+]] = zext i8 [[LOAD1]] to i32 +; CHECK: [[LOAD2:%[a-z]+]] = load i8* %mem2, align 1 +; CHECK: [[ZEXT2:%[a-z]+]] = zext i8 [[LOAD2]] to i32 +; CHECK: [[RET:%[a-z]+]] = sub i32 [[ZEXT1]], [[ZEXT2]] + ret i32 %ret +; CHECK: ret i32 [[RET]] +} + +; Check memcmp(mem1, mem2, size) -> cnst, where all arguments are constants. + +define i32 @test_simplify4() { +; CHECK: @test_simplify4 + %mem1 = getelementptr [4 x i8]* @hel, i32 0, i32 0 + %mem2 = getelementptr [8 x i8]* @hello_u, i32 0, i32 0 + %ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 3) + ret i32 %ret +; CHECK: ret i32 0 +} + +define i32 @test_simplify5() { +; CHECK: @test_simplify5 + %mem1 = getelementptr [4 x i8]* @hel, i32 0, i32 0 + %mem2 = getelementptr [4 x i8]* @foo, i32 0, i32 0 + %ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 3) + ret i32 %ret +; CHECK: ret i32 {{[0-9]+}} +} + +define i32 @test_simplify6() { +; CHECK: @test_simplify6 + %mem1 = getelementptr [4 x i8]* @foo, i32 0, i32 0 + %mem2 = getelementptr [4 x i8]* @hel, i32 0, i32 0 + %ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 3) + ret i32 %ret +; CHECK: ret i32 {{-[0-9]+}} +} diff --git a/test/Transforms/InstCombine/memcmp-2.ll b/test/Transforms/InstCombine/memcmp-2.ll new file mode 100644 index 0000000..3796117 --- /dev/null +++ b/test/Transforms/InstCombine/memcmp-2.ll @@ -0,0 +1,17 @@ +; Test that the memcmp library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +declare i32* @memcmp(i8*, i8*, i32) + +; Check that memcmp functions with the wrong prototype aren't simplified. + +define i32* @test_no_simplify1(i8* %mem, i32 %size) { +; CHECK: @test_no_simplify1 + %ret = call i32* @memcmp(i8* %mem, i8* %mem, i32 %size) +; CHECK-NEXT: call i32* @memcmp + ret i32* %ret +; CHECK-NEXT: ret i32* %ret +} diff --git a/test/Transforms/InstCombine/memcpy-1.ll b/test/Transforms/InstCombine/memcpy-1.ll new file mode 100644 index 0000000..65b79ad --- /dev/null +++ b/test/Transforms/InstCombine/memcpy-1.ll @@ -0,0 +1,17 @@ +; Test that the memcpy library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +declare i8* @memcpy(i8*, i8*, i32) + +; Check memcpy(mem1, mem2, size) -> llvm.memcpy(mem1, mem2, size, 1). + +define i8* @test_simplify1(i8* %mem1, i8* %mem2, i32 %size) { +; CHECK: @test_simplify1 + %ret = call i8* @memcpy(i8* %mem1, i8* %mem2, i32 %size) +; CHECK: call void @llvm.memcpy + ret i8* %ret +; CHECK: ret i8* %mem1 +} diff --git a/test/Transforms/InstCombine/memcpy-2.ll b/test/Transforms/InstCombine/memcpy-2.ll new file mode 100644 index 0000000..4a8a020 --- /dev/null +++ b/test/Transforms/InstCombine/memcpy-2.ll @@ -0,0 +1,17 @@ +; Test that the memcpy library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +declare i8 @memcpy(i8*, i8*, i32) + +; Check that memcpy functions with the wrong prototype aren't simplified. + +define i8 @test_no_simplify1(i8* %mem1, i8* %mem2, i32 %size) { +; CHECK: @test_no_simplify1 + %ret = call i8 @memcpy(i8* %mem1, i8* %mem2, i32 %size) +; CHECK: call i8 @memcpy + ret i8 %ret +; CHECK: ret i8 %ret +} diff --git a/test/Transforms/InstCombine/memcpy-from-global.ll b/test/Transforms/InstCombine/memcpy-from-global.ll new file mode 100644 index 0000000..83c893e --- /dev/null +++ b/test/Transforms/InstCombine/memcpy-from-global.ll @@ -0,0 +1,136 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64" +@C.0.1248 = internal constant [128 x float] [ float -1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00 ], align 32 ; <[128 x float]*> [#uses=1] + +define float @test1(i32 %hash, float %x, float %y, float %z, float %w) { +entry: + %lookupTable = alloca [128 x float], align 16 ; <[128 x float]*> [#uses=5] + %lookupTable1 = bitcast [128 x float]* %lookupTable to i8* ; <i8*> [#uses=1] + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %lookupTable1, i8* bitcast ([128 x float]* @C.0.1248 to i8*), i64 512, i32 16, i1 false) + +; CHECK: @test1 +; CHECK-NOT: alloca +; CHECK-NOT: call{{.*}}@llvm.memcpy + + %tmp3 = shl i32 %hash, 2 ; <i32> [#uses=1] + %tmp5 = and i32 %tmp3, 124 ; <i32> [#uses=4] + %tmp753 = getelementptr [128 x float]* %lookupTable, i32 0, i32 %tmp5 ; <float*> [#uses=1] + %tmp9 = load float* %tmp753 ; <float> [#uses=1] + %tmp11 = fmul float %tmp9, %x ; <float> [#uses=1] + %tmp13 = fadd float %tmp11, 0.000000e+00 ; <float> [#uses=1] + %tmp17.sum52 = or i32 %tmp5, 1 ; <i32> [#uses=1] + %tmp1851 = getelementptr [128 x float]* %lookupTable, i32 0, i32 %tmp17.sum52 ; <float*> [#uses=1] + %tmp19 = load float* %tmp1851 ; <float> [#uses=1] + %tmp21 = fmul float %tmp19, %y ; <float> [#uses=1] + %tmp23 = fadd float %tmp21, %tmp13 ; <float> [#uses=1] + %tmp27.sum50 = or i32 %tmp5, 2 ; <i32> [#uses=1] + %tmp2849 = getelementptr [128 x float]* %lookupTable, i32 0, i32 %tmp27.sum50 ; <float*> [#uses=1] + %tmp29 = load float* %tmp2849 ; <float> [#uses=1] + %tmp31 = fmul float %tmp29, %z ; <float> [#uses=1] + %tmp33 = fadd float %tmp31, %tmp23 ; <float> [#uses=1] + %tmp37.sum48 = or i32 %tmp5, 3 ; <i32> [#uses=1] + %tmp3847 = getelementptr [128 x float]* %lookupTable, i32 0, i32 %tmp37.sum48 ; <float*> [#uses=1] + %tmp39 = load float* %tmp3847 ; <float> [#uses=1] + %tmp41 = fmul float %tmp39, %w ; <float> [#uses=1] + %tmp43 = fadd float %tmp41, %tmp33 ; <float> [#uses=1] + ret float %tmp43 +} + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind + +%T = type { i8, [123 x i8] } +%U = type { i32, i32, i32, i32, i32 } + +@G = constant %T {i8 1, [123 x i8] zeroinitializer } +@H = constant [2 x %U] zeroinitializer, align 16 + +define void @test2() { + %A = alloca %T + %B = alloca %T + %a = bitcast %T* %A to i8* + %b = bitcast %T* %B to i8* + +; CHECK: @test2 + +; %A alloca is deleted +; CHECK-NEXT: alloca [124 x i8] +; CHECK-NEXT: getelementptr inbounds [124 x i8]* + +; use @G instead of %A +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* getelementptr inbounds (%T* @G, i64 0, i32 0) + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* bitcast (%T* @G to i8*), i64 124, i32 4, i1 false) + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %b, i8* %a, i64 124, i32 4, i1 false) + call void @bar(i8* %b) + ret void +} + +declare void @bar(i8*) + + +;; Should be able to eliminate the alloca. +define void @test3() { + %A = alloca %T + %a = bitcast %T* %A to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* bitcast (%T* @G to i8*), i64 124, i32 4, i1 false) + call void @bar(i8* %a) readonly +; CHECK: @test3 +; CHECK-NEXT: call void @bar(i8* getelementptr inbounds (%T* @G, i64 0, i32 0)) + ret void +} + +define void @test4() { + %A = alloca %T + %a = bitcast %T* %A to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* bitcast (%T* @G to i8*), i64 124, i32 4, i1 false) + call void @baz(i8* byval %a) +; CHECK: @test4 +; CHECK-NEXT: call void @baz(i8* byval getelementptr inbounds (%T* @G, i64 0, i32 0)) + ret void +} + +declare void @llvm.lifetime.start(i64, i8*) +define void @test5() { + %A = alloca %T + %a = bitcast %T* %A to i8* + call void @llvm.lifetime.start(i64 -1, i8* %a) + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* bitcast (%T* @G to i8*), i64 124, i32 4, i1 false) + call void @baz(i8* byval %a) +; CHECK: @test5 +; CHECK-NEXT: call void @baz(i8* byval getelementptr inbounds (%T* @G, i64 0, i32 0)) + ret void +} + + +declare void @baz(i8* byval) + + +define void @test6() { + %A = alloca %U, align 16 + %a = bitcast %U* %A to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* bitcast ([2 x %U]* @H to i8*), i64 20, i32 16, i1 false) + call void @bar(i8* %a) readonly +; CHECK: @test6 +; CHECK-NEXT: call void @bar(i8* bitcast ([2 x %U]* @H to i8*)) + ret void +} + +define void @test7() { + %A = alloca %U, align 16 + %a = bitcast %U* %A to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* bitcast (%U* getelementptr ([2 x %U]* @H, i64 0, i32 0) to i8*), i64 20, i32 4, i1 false) + call void @bar(i8* %a) readonly +; CHECK: @test7 +; CHECK-NEXT: call void @bar(i8* bitcast ([2 x %U]* @H to i8*)) + ret void +} + +define void @test8() { + %A = alloca %U, align 16 + %a = bitcast %U* %A to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* bitcast (%U* getelementptr ([2 x %U]* @H, i64 0, i32 1) to i8*), i64 20, i32 4, i1 false) + call void @bar(i8* %a) readonly +; CHECK: @test8 +; CHECK: llvm.memcpy +; CHECK: bar + ret void +} diff --git a/test/Transforms/InstCombine/memcpy_chk-1.ll b/test/Transforms/InstCombine/memcpy_chk-1.ll new file mode 100644 index 0000000..7c7d918 --- /dev/null +++ b/test/Transforms/InstCombine/memcpy_chk-1.ll @@ -0,0 +1,60 @@ +; Test lib call simplification of __memcpy_chk calls with various values +; for dstlen and len. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" + +%struct.T1 = type { [100 x i32], [100 x i32], [1024 x i8] } +%struct.T2 = type { [100 x i32], [100 x i32], [1024 x i8] } +%struct.T3 = type { [100 x i32], [100 x i32], [2048 x i8] } + +@t1 = common global %struct.T1 zeroinitializer +@t2 = common global %struct.T2 zeroinitializer +@t3 = common global %struct.T3 zeroinitializer + +; Check cases where dstlen >= len. + +define void @test_simplify1() { +; CHECK: @test_simplify1 + %dst = bitcast %struct.T1* @t1 to i8* + %src = bitcast %struct.T2* @t2 to i8* + +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64 + call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1824, i64 1824) + ret void +} + +define void @test_simplify2() { +; CHECK: @test_simplify2 + %dst = bitcast %struct.T1* @t1 to i8* + %src = bitcast %struct.T3* @t3 to i8* + +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64 + call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1824, i64 2848) + ret void +} + +; Check cases where dstlen < len. + +define void @test_no_simplify1() { +; CHECK: @test_no_simplify1 + %dst = bitcast %struct.T3* @t3 to i8* + %src = bitcast %struct.T1* @t1 to i8* + +; CHECK-NEXT: call i8* @__memcpy_chk + call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 2848, i64 1824) + ret void +} + +define void @test_no_simplify2() { +; CHECK: @test_no_simplify2 + %dst = bitcast %struct.T1* @t1 to i8* + %src = bitcast %struct.T2* @t2 to i8* + +; CHECK-NEXT: call i8* @__memcpy_chk + call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1024, i64 0) + ret void +} + +declare i8* @__memcpy_chk(i8*, i8*, i64, i64) diff --git a/test/Transforms/InstCombine/memcpy_chk-2.ll b/test/Transforms/InstCombine/memcpy_chk-2.ll new file mode 100644 index 0000000..aa43029 --- /dev/null +++ b/test/Transforms/InstCombine/memcpy_chk-2.ll @@ -0,0 +1,24 @@ +; Test that lib call simplification doesn't simplify __memcpy_chk calls +; with the wrong prototype. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" + +%struct.T1 = type { [100 x i32], [100 x i32], [1024 x i8] } +%struct.T2 = type { [100 x i32], [100 x i32], [1024 x i8] } + +@t1 = common global %struct.T1 zeroinitializer +@t2 = common global %struct.T2 zeroinitializer + +define void @test_no_simplify() { +; CHECK: @test_no_simplify + %dst = bitcast %struct.T1* @t1 to i8* + %src = bitcast %struct.T2* @t2 to i8* + +; CHECK-NEXT: call i8* @__memcpy_chk + call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1824) + ret void +} + +declare i8* @__memcpy_chk(i8*, i8*, i64) diff --git a/test/Transforms/InstCombine/memmove-1.ll b/test/Transforms/InstCombine/memmove-1.ll new file mode 100644 index 0000000..53f2f11 --- /dev/null +++ b/test/Transforms/InstCombine/memmove-1.ll @@ -0,0 +1,17 @@ +; Test that the memmove library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +declare i8* @memmove(i8*, i8*, i32) + +; Check memmove(mem1, mem2, size) -> llvm.memmove(mem1, mem2, size, 1). + +define i8* @test_simplify1(i8* %mem1, i8* %mem2, i32 %size) { +; CHECK: @test_simplify1 + %ret = call i8* @memmove(i8* %mem1, i8* %mem2, i32 %size) +; CHECK: call void @llvm.memmove + ret i8* %ret +; CHECK: ret i8* %mem1 +} diff --git a/test/Transforms/InstCombine/memmove-2.ll b/test/Transforms/InstCombine/memmove-2.ll new file mode 100644 index 0000000..23887bc --- /dev/null +++ b/test/Transforms/InstCombine/memmove-2.ll @@ -0,0 +1,17 @@ +; Test that the memmove library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +declare i8 @memmove(i8*, i8*, i32) + +; Check that memmove functions with the wrong prototype aren't simplified. + +define i8 @test_no_simplify1(i8* %mem1, i8* %mem2, i32 %size) { +; CHECK: @test_no_simplify1 + %ret = call i8 @memmove(i8* %mem1, i8* %mem2, i32 %size) +; CHECK: call i8 @memmove + ret i8 %ret +; CHECK: ret i8 %ret +} diff --git a/test/Transforms/InstCombine/memmove_chk-1.ll b/test/Transforms/InstCombine/memmove_chk-1.ll new file mode 100644 index 0000000..f9ff9a1 --- /dev/null +++ b/test/Transforms/InstCombine/memmove_chk-1.ll @@ -0,0 +1,60 @@ +; Test lib call simplification of __memmove_chk calls with various values +; for dstlen and len. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" + +%struct.T1 = type { [100 x i32], [100 x i32], [1024 x i8] } +%struct.T2 = type { [100 x i32], [100 x i32], [1024 x i8] } +%struct.T3 = type { [100 x i32], [100 x i32], [2048 x i8] } + +@t1 = common global %struct.T1 zeroinitializer +@t2 = common global %struct.T2 zeroinitializer +@t3 = common global %struct.T3 zeroinitializer + +; Check cases where dstlen >= len. + +define void @test_simplify1() { +; CHECK: @test_simplify1 + %dst = bitcast %struct.T1* @t1 to i8* + %src = bitcast %struct.T2* @t2 to i8* + +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64 + call i8* @__memmove_chk(i8* %dst, i8* %src, i64 1824, i64 1824) + ret void +} + +define void @test_simplify2() { +; CHECK: @test_simplify2 + %dst = bitcast %struct.T1* @t1 to i8* + %src = bitcast %struct.T3* @t3 to i8* + +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64 + call i8* @__memmove_chk(i8* %dst, i8* %src, i64 1824, i64 2848) + ret void +} + +; Check cases where dstlen < len. + +define void @test_no_simplify1() { +; CHECK: @test_no_simplify1 + %dst = bitcast %struct.T3* @t3 to i8* + %src = bitcast %struct.T1* @t1 to i8* + +; CHECK-NEXT: call i8* @__memmove_chk + call i8* @__memmove_chk(i8* %dst, i8* %src, i64 2848, i64 1824) + ret void +} + +define void @test_no_simplify2() { +; CHECK: @test_no_simplify2 + %dst = bitcast %struct.T1* @t1 to i8* + %src = bitcast %struct.T2* @t2 to i8* + +; CHECK-NEXT: call i8* @__memmove_chk + call i8* @__memmove_chk(i8* %dst, i8* %src, i64 1024, i64 0) + ret void +} + +declare i8* @__memmove_chk(i8*, i8*, i64, i64) diff --git a/test/Transforms/InstCombine/memmove_chk-2.ll b/test/Transforms/InstCombine/memmove_chk-2.ll new file mode 100644 index 0000000..f0a915f --- /dev/null +++ b/test/Transforms/InstCombine/memmove_chk-2.ll @@ -0,0 +1,24 @@ +; Test that lib call simplification doesn't simplify __memmove_chk calls +; with the wrong prototype. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" + +%struct.T1 = type { [100 x i32], [100 x i32], [1024 x i8] } +%struct.T2 = type { [100 x i32], [100 x i32], [1024 x i8] } + +@t1 = common global %struct.T1 zeroinitializer +@t2 = common global %struct.T2 zeroinitializer + +define void @test_no_simplify() { +; CHECK: @test_no_simplify + %dst = bitcast %struct.T1* @t1 to i8* + %src = bitcast %struct.T2* @t2 to i8* + +; CHECK-NEXT: call i8* @__memmove_chk + call i8* @__memmove_chk(i8* %dst, i8* %src, i64 1824) + ret void +} + +declare i8* @__memmove_chk(i8*, i8*, i64) diff --git a/test/Transforms/InstCombine/memset-1.ll b/test/Transforms/InstCombine/memset-1.ll new file mode 100644 index 0000000..48b433e --- /dev/null +++ b/test/Transforms/InstCombine/memset-1.ll @@ -0,0 +1,17 @@ +; Test that the memset library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +declare i8* @memset(i8*, i32, i32) + +; Check memset(mem1, val, size) -> llvm.memset(mem1, val, size, 1). + +define i8* @test_simplify1(i8* %mem, i32 %val, i32 %size) { +; CHECK: @test_simplify1 + %ret = call i8* @memset(i8* %mem, i32 %val, i32 %size) +; CHECK: call void @llvm.memset + ret i8* %ret +; CHECK: ret i8* %mem +} diff --git a/test/Transforms/InstCombine/memset-2.ll b/test/Transforms/InstCombine/memset-2.ll new file mode 100644 index 0000000..8a90333 --- /dev/null +++ b/test/Transforms/InstCombine/memset-2.ll @@ -0,0 +1,17 @@ +; Test that the memset library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +declare i8 @memset(i8*, i32, i32) + +; Check that memset functions with the wrong prototype aren't simplified. + +define i8 @test_no_simplify1(i8* %mem, i32 %val, i32 %size) { +; CHECK: @test_no_simplify1 + %ret = call i8 @memset(i8* %mem, i32 %val, i32 %size) +; CHECK: call i8 @memset + ret i8 %ret +; CHECK: ret i8 %ret +} diff --git a/test/Transforms/InstCombine/memset_chk-1.ll b/test/Transforms/InstCombine/memset_chk-1.ll new file mode 100644 index 0000000..be4c1cf --- /dev/null +++ b/test/Transforms/InstCombine/memset_chk-1.ll @@ -0,0 +1,61 @@ +; Test lib call simplification of __memset_chk calls with various values +; for dstlen and len. +; +; RUN: opt < %s -instcombine -S | FileCheck %s +; rdar://7719085 + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" + +%struct.T = type { [100 x i32], [100 x i32], [1024 x i8] } +@t = common global %struct.T zeroinitializer + +; Check cases where dstlen >= len. + +define void @test_simplify1() { +; CHECK: @test_simplify1 + %dst = bitcast %struct.T* @t to i8* + +; CHECK-NEXT: call void @llvm.memset.p0i8.i64 + call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 1824) + ret void +} + +define void @test_simplify2() { +; CHECK: @test_simplify2 + %dst = bitcast %struct.T* @t to i8* + +; CHECK-NEXT: call void @llvm.memset.p0i8.i64 + call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 3648) + ret void +} + +define void @test_simplify3() { +; CHECK: @test_simplify3 + %dst = bitcast %struct.T* @t to i8* + +; CHECK-NEXT: call void @llvm.memset.p0i8.i64 + call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 -1) + ret void +} + +; Check cases where dstlen < len. + +define void @test_no_simplify1() { +; CHECK: @test_no_simplify1 + %dst = bitcast %struct.T* @t to i8* + +; CHECK-NEXT: call i8* @__memset_chk + call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 400) + ret void +} + +define void @test_no_simplify2() { +; CHECK: @test_no_simplify2 + %dst = bitcast %struct.T* @t to i8* + +; CHECK-NEXT: call i8* @__memset_chk + call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 0) + ret void +} + +declare i8* @__memset_chk(i8*, i32, i64, i64) diff --git a/test/Transforms/InstCombine/memset_chk-2.ll b/test/Transforms/InstCombine/memset_chk-2.ll new file mode 100644 index 0000000..60fbf16 --- /dev/null +++ b/test/Transforms/InstCombine/memset_chk-2.ll @@ -0,0 +1,20 @@ +; Test that lib call simplification doesn't simplify __memset_chk calls +; with the wrong prototype. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" + +%struct.T = type { [100 x i32], [100 x i32], [1024 x i8] } +@t = common global %struct.T zeroinitializer + +define void @test_no_simplify() { +; CHECK: @test_no_simplify + %dst = bitcast %struct.T* @t to i8* + +; CHECK-NEXT: call i8* @__memset_chk + call i8* @__memset_chk(i8* %dst, i32 0, i64 1824) + ret void +} + +declare i8* @__memset_chk(i8*, i32, i64) diff --git a/test/Transforms/InstCombine/memset_chk.ll b/test/Transforms/InstCombine/memset_chk.ll deleted file mode 100644 index 58ecda5..0000000 --- a/test/Transforms/InstCombine/memset_chk.ll +++ /dev/null @@ -1,18 +0,0 @@ -; RUN: opt < %s -instcombine -S | FileCheck %s -; rdar://7719085 - -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" - -%struct.data = type { [100 x i32], [100 x i32], [1024 x i8] } - -define i32 @t() nounwind ssp { -; CHECK: @t -; CHECK: @llvm.memset.p0i8.i64 -entry: - %0 = alloca %struct.data, align 8 ; <%struct.data*> [#uses=1] - %1 = bitcast %struct.data* %0 to i8* ; <i8*> [#uses=1] - %2 = call i8* @__memset_chk(i8* %1, i32 0, i64 1824, i64 1824) nounwind ; <i8*> [#uses=0] - ret i32 0 -} - -declare i8* @__memset_chk(i8*, i32, i64, i64) nounwind diff --git a/test/Transforms/InstCombine/obfuscated_splat.ll b/test/Transforms/InstCombine/obfuscated_splat.ll new file mode 100644 index 0000000..c25dade --- /dev/null +++ b/test/Transforms/InstCombine/obfuscated_splat.ll @@ -0,0 +1,11 @@ +; RUN: opt -instcombine -S %s | FileCheck %s + +define void @test(<4 x float> *%in_ptr, <4 x float> *%out_ptr) { + %A = load <4 x float>* %in_ptr, align 16 + %B = shufflevector <4 x float> %A, <4 x float> undef, <4 x i32> <i32 0, i32 0, i32 undef, i32 undef> + %C = shufflevector <4 x float> %B, <4 x float> %A, <4 x i32> <i32 0, i32 1, i32 4, i32 undef> + %D = shufflevector <4 x float> %C, <4 x float> %A, <4 x i32> <i32 0, i32 1, i32 2, i32 4> +; CHECK: %D = shufflevector <4 x float> %A, <4 x float> undef, <4 x i32> zeroinitializer + store <4 x float> %D, <4 x float> *%out_ptr + ret void +} diff --git a/test/Transforms/InstCombine/objsize.ll b/test/Transforms/InstCombine/objsize.ll index d7e2921..31a3cb4 100644 --- a/test/Transforms/InstCombine/objsize.ll +++ b/test/Transforms/InstCombine/objsize.ll @@ -247,7 +247,8 @@ entry: ; technically reachable, but this malformed IR may appear as a result of constant propagation xpto: - %gep = getelementptr i8* %gep, i32 1 + %gep2 = getelementptr i8* %gep, i32 1 + %gep = getelementptr i8* %gep2, i32 1 %o = call i32 @llvm.objectsize.i32(i8* %gep, i1 true) ; CHECK: ret i32 undef ret i32 %o diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll index 4baae26..cc3aacd 100644 --- a/test/Transforms/InstCombine/select.ll +++ b/test/Transforms/InstCombine/select.ll @@ -829,3 +829,37 @@ define i1 @test63(i1 %A, i1 %B) { ; CHECK: %C = or i1 %B, %not ; CHECK: ret i1 %C } + +; PR14131 +define void @test64(i32 %p, i16 %b) noreturn nounwind { +entry: + %p.addr.0.insert.mask = and i32 %p, -65536 + %conv2 = and i32 %p, 65535 + br i1 undef, label %lor.rhs, label %lor.end + +lor.rhs: + %p.addr.0.extract.trunc = trunc i32 %p.addr.0.insert.mask to i16 + %phitmp = zext i16 %p.addr.0.extract.trunc to i32 + br label %lor.end + +lor.end: + %t.1 = phi i32 [ 0, %entry ], [ %phitmp, %lor.rhs ] + %conv6 = zext i16 %b to i32 + %div = udiv i32 %conv6, %t.1 + %tobool8 = icmp eq i32 %div, 0 + %cmp = icmp eq i32 %t.1, 0 + %cmp12 = icmp ult i32 %conv2, 2 + %cmp.sink = select i1 %tobool8, i1 %cmp12, i1 %cmp + br i1 %cmp.sink, label %cond.end17, label %cond.false16 + +cond.false16: + br label %cond.end17 + +cond.end17: + br label %while.body + +while.body: + br label %while.body +; CHECK: @test64 +; CHECK-NOT: select +} diff --git a/test/Transforms/InstCombine/stpcpy-1.ll b/test/Transforms/InstCombine/stpcpy-1.ll new file mode 100644 index 0000000..8b6bb0e --- /dev/null +++ b/test/Transforms/InstCombine/stpcpy-1.ll @@ -0,0 +1,46 @@ +; Test that the stpcpy library call simplifier works correctly. +; RUN: opt < %s -instcombine -S | FileCheck %s +; +; This transformation requires the pointer size, as it assumes that size_t is +; the size of a pointer. +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" + +@hello = constant [6 x i8] c"hello\00" +@a = common global [32 x i8] zeroinitializer, align 1 +@b = common global [32 x i8] zeroinitializer, align 1 + +declare i8* @stpcpy(i8*, i8*) + +define i8* @test_simplify1() { +; CHECK: @test_simplify1 + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + + %ret = call i8* @stpcpy(i8* %dst, i8* %src) +; CHECK: @llvm.memcpy.p0i8.p0i8.i32 +; CHECK-NEXT: getelementptr inbounds ([32 x i8]* @a, i32 0, i32 5) + ret i8* %ret +} + +define i8* @test_simplify2() { +; CHECK: @test_simplify2 + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + + %ret = call i8* @stpcpy(i8* %dst, i8* %dst) +; CHECK: [[LEN:%[a-z]+]] = call i32 @strlen +; CHECK-NEXT: getelementptr inbounds [32 x i8]* @a, i32 0, i32 [[LEN]] + ret i8* %ret +} + +define i8* @test_no_simplify1() { +; CHECK: @test_no_simplify1 + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [32 x i8]* @b, i32 0, i32 0 + + %ret = call i8* @stpcpy(i8* %dst, i8* %src) +; CHECK: call i8* @stpcpy + ret i8* %ret +} diff --git a/test/Transforms/InstCombine/stpcpy-2.ll b/test/Transforms/InstCombine/stpcpy-2.ll new file mode 100644 index 0000000..2e92c08 --- /dev/null +++ b/test/Transforms/InstCombine/stpcpy-2.ll @@ -0,0 +1,22 @@ +; Test that the stpcpy library call simplifier works correctly. +; RUN: opt < %s -instcombine -S | FileCheck %s +; +; This transformation requires the pointer size, as it assumes that size_t is +; the size of a pointer. +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" + +@hello = constant [6 x i8] c"hello\00" +@a = common global [32 x i8] zeroinitializer, align 1 + +declare i16* @stpcpy(i8*, i8*) + +define void @test_no_simplify1() { +; CHECK: @test_no_simplify1 + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + + call i16* @stpcpy(i8* %dst, i8* %src) +; CHECK: call i16* @stpcpy + ret void +} diff --git a/test/Transforms/InstCombine/stpcpy_chk-1.ll b/test/Transforms/InstCombine/stpcpy_chk-1.ll new file mode 100644 index 0000000..0560391 --- /dev/null +++ b/test/Transforms/InstCombine/stpcpy_chk-1.ll @@ -0,0 +1,96 @@ +; Test lib call simplification of __stpcpy_chk calls with various values +; for src, dst, and slen. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@a = common global [60 x i8] zeroinitializer, align 1 +@b = common global [60 x i8] zeroinitializer, align 1 +@.str = private constant [12 x i8] c"abcdefghijk\00" + +; Check cases where slen >= strlen (src). + +define void @test_simplify1() { +; CHECK: @test_simplify1 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [12 x i8]* @.str, i32 0, i32 0 + +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32 + call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 60) + ret void +} + +define void @test_simplify2() { +; CHECK: @test_simplify2 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [12 x i8]* @.str, i32 0, i32 0 + +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32 + call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 12) + ret void +} + +define void @test_simplify3() { +; CHECK: @test_simplify3 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [12 x i8]* @.str, i32 0, i32 0 + +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32 + call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 -1) + ret void +} + +; Check cases where there are no string constants. + +define void @test_simplify4() { +; CHECK: @test_simplify4 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [60 x i8]* @b, i32 0, i32 0 + +; CHECK-NEXT: call i8* @stpcpy + call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 -1) + ret void +} + +; Check case where the string length is not constant. + +define i8* @test_simplify5() { +; CHECK: @test_simplify5 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [12 x i8]* @.str, i32 0, i32 0 + +; CHECK: @__memcpy_chk + %len = call i32 @llvm.objectsize.i32(i8* %dst, i1 false) + %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 %len) +; CHECK: ret i8* getelementptr inbounds ([60 x i8]* @a, i32 0, i32 11) + ret i8* %ret +} + +; Check case where the source and destination are the same. + +define i8* @test_simplify6() { +; CHECK: @test_simplify6 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + +; CHECK: [[LEN:%[a-z]+]] = call i32 @strlen +; CHECK-NEXT: getelementptr inbounds [60 x i8]* @a, i32 0, i32 [[LEN]] + %len = call i32 @llvm.objectsize.i32(i8* %dst, i1 false) + %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %dst, i32 %len) + ret i8* %ret +} + +; Check case where slen < strlen (src). + +define void @test_no_simplify1() { +; CHECK: @test_no_simplify1 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [60 x i8]* @b, i32 0, i32 0 + +; CHECK-NEXT: call i8* @__stpcpy_chk + call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 8) + ret void +} + +declare i8* @__stpcpy_chk(i8*, i8*, i32) nounwind +declare i32 @llvm.objectsize.i32(i8*, i1) nounwind readonly diff --git a/test/Transforms/InstCombine/stpcpy_chk-2.ll b/test/Transforms/InstCombine/stpcpy_chk-2.ll new file mode 100644 index 0000000..46c2139 --- /dev/null +++ b/test/Transforms/InstCombine/stpcpy_chk-2.ll @@ -0,0 +1,21 @@ +; Test that lib call simplification doesn't simplify __stpcpy_chk calls +; with the wrong prototype. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@a = common global [60 x i16] zeroinitializer, align 1 +@.str = private constant [8 x i8] c"abcdefg\00" + +define void @test_no_simplify() { +; CHECK: @test_no_simplify + %dst = getelementptr inbounds [60 x i16]* @a, i32 0, i32 0 + %src = getelementptr inbounds [8 x i8]* @.str, i32 0, i32 0 + +; CHECK-NEXT: call i16* @__strcpy_chk + call i16* @__strcpy_chk(i16* %dst, i8* %src, i32 8) + ret void +} + +declare i16* @__strcpy_chk(i16*, i8*, i32) diff --git a/test/Transforms/InstCombine/strcat-1.ll b/test/Transforms/InstCombine/strcat-1.ll new file mode 100644 index 0000000..3c05d6b --- /dev/null +++ b/test/Transforms/InstCombine/strcat-1.ll @@ -0,0 +1,38 @@ +; Test that the strcat libcall simplifier works correctly per the +; bug found in PR3661. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" +@null = constant [1 x i8] zeroinitializer +@null_hello = constant [7 x i8] c"\00hello\00" + +declare i8* @strcat(i8*, i8*) +declare i32 @puts(i8*) + +define i32 @main() { +; CHECK: @main +; CHECK-NOT: call i8* @strcat +; CHECK: call i32 @puts + + %target = alloca [1024 x i8] + %arg1 = getelementptr [1024 x i8]* %target, i32 0, i32 0 + store i8 0, i8* %arg1 + + ; rslt1 = strcat(target, "hello\00") + %arg2 = getelementptr [6 x i8]* @hello, i32 0, i32 0 + %rslt1 = call i8* @strcat(i8* %arg1, i8* %arg2) + + ; rslt2 = strcat(rslt1, "\00") + %arg3 = getelementptr [1 x i8]* @null, i32 0, i32 0 + %rslt2 = call i8* @strcat(i8* %rslt1, i8* %arg3) + + ; rslt3 = strcat(rslt2, "\00hello\00") + %arg4 = getelementptr [7 x i8]* @null_hello, i32 0, i32 0 + %rslt3 = call i8* @strcat(i8* %rslt2, i8* %arg4) + + call i32 @puts( i8* %rslt3 ) + ret i32 0 +} diff --git a/test/Transforms/InstCombine/strcat-2.ll b/test/Transforms/InstCombine/strcat-2.ll new file mode 100644 index 0000000..379ee74 --- /dev/null +++ b/test/Transforms/InstCombine/strcat-2.ll @@ -0,0 +1,32 @@ +; Test that the strcat libcall simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" +@empty = constant [1 x i8] c"\00" +@a = common global [32 x i8] zeroinitializer, align 1 + +declare i8* @strcat(i8*, i8*) + +define void @test_simplify1() { +; CHECK: @test_simplify1 +; CHECK-NOT: call i8* @strcat +; CHECK: ret void + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + call i8* @strcat(i8* %dst, i8* %src) + ret void +} + +define void @test_simplify2() { +; CHECK: @test_simplify2 +; CHECK-NEXT: ret void + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [1 x i8]* @empty, i32 0, i32 0 + call i8* @strcat(i8* %dst, i8* %src) + ret void +} diff --git a/test/Transforms/InstCombine/strcat-3.ll b/test/Transforms/InstCombine/strcat-3.ll new file mode 100644 index 0000000..15aff2f --- /dev/null +++ b/test/Transforms/InstCombine/strcat-3.ll @@ -0,0 +1,22 @@ +; Test that the strcat libcall simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" +@empty = constant [1 x i8] c"\00" +@a = common global [32 x i8] zeroinitializer, align 1 + +declare i16* @strcat(i8*, i8*) + +define void @test_nosimplify1() { +; CHECK: @test_nosimplify1 +; CHECK: call i16* @strcat +; CHECK: ret void + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + call i16* @strcat(i8* %dst, i8* %src) + ret void +} diff --git a/test/Transforms/InstCombine/strchr-1.ll b/test/Transforms/InstCombine/strchr-1.ll new file mode 100644 index 0000000..5efab9e --- /dev/null +++ b/test/Transforms/InstCombine/strchr-1.ll @@ -0,0 +1,54 @@ +; Test that the strchr library call simplifier works correctly. +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [14 x i8] c"hello world\5Cn\00" +@null = constant [1 x i8] zeroinitializer +@chp = global i8* zeroinitializer + +declare i8* @strchr(i8*, i32) + +define void @test_simplify1() { +; CHECK: store i8* getelementptr inbounds ([14 x i8]* @hello, i32 0, i32 6) +; CHECK-NOT: call i8* @strchr +; CHECK: ret void + + %str = getelementptr [14 x i8]* @hello, i32 0, i32 0 + %dst = call i8* @strchr(i8* %str, i32 119) + store i8* %dst, i8** @chp + ret void +} + +define void @test_simplify2() { +; CHECK: store i8* null, i8** @chp, align 4 +; CHECK-NOT: call i8* @strchr +; CHECK: ret void + + %str = getelementptr [1 x i8]* @null, i32 0, i32 0 + %dst = call i8* @strchr(i8* %str, i32 119) + store i8* %dst, i8** @chp + ret void +} + +define void @test_simplify3() { +; CHECK: store i8* getelementptr inbounds ([14 x i8]* @hello, i32 0, i32 13) +; CHECK-NOT: call i8* @strchr +; CHECK: ret void + + %src = getelementptr [14 x i8]* @hello, i32 0, i32 0 + %dst = call i8* @strchr(i8* %src, i32 0) + store i8* %dst, i8** @chp + ret void +} + +define void @test_simplify4(i32 %chr) { +; CHECK: call i8* @memchr +; CHECK-NOT: call i8* @strchr +; CHECK: ret void + + %src = getelementptr [14 x i8]* @hello, i32 0, i32 0 + %dst = call i8* @strchr(i8* %src, i32 %chr) + store i8* %dst, i8** @chp + ret void +} diff --git a/test/Transforms/InstCombine/strchr-2.ll b/test/Transforms/InstCombine/strchr-2.ll new file mode 100644 index 0000000..35bbd23 --- /dev/null +++ b/test/Transforms/InstCombine/strchr-2.ll @@ -0,0 +1,21 @@ +; Test that the strchr libcall simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [14 x i8] c"hello world\5Cn\00" +@chr = global i8 zeroinitializer + +declare i8 @strchr(i8*, i32) + +define void @test_nosimplify1() { +; CHECK: test_nosimplify1 +; CHECK: call i8 @strchr +; CHECK: ret void + + %str = getelementptr [14 x i8]* @hello, i32 0, i32 0 + %dst = call i8 @strchr(i8* %str, i32 119) + store i8 %dst, i8* @chr + ret void +} diff --git a/test/Transforms/InstCombine/strcmp-1.ll b/test/Transforms/InstCombine/strcmp-1.ll new file mode 100644 index 0000000..0679246 --- /dev/null +++ b/test/Transforms/InstCombine/strcmp-1.ll @@ -0,0 +1,82 @@ +; Test that the strcmp library call simplifier works correctly. +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" +@hell = constant [5 x i8] c"hell\00" +@bell = constant [5 x i8] c"bell\00" +@null = constant [1 x i8] zeroinitializer + +declare i32 @strcmp(i8*, i8*) + +; strcmp("", x) -> -*x +define i32 @test1(i8* %str2) { +; CHECK: @test1 +; CHECK: %strcmpload = load i8* %str +; CHECK: %1 = zext i8 %strcmpload to i32 +; CHECK: %2 = sub i32 0, %1 +; CHECK: ret i32 %2 + + %str1 = getelementptr inbounds [1 x i8]* @null, i32 0, i32 0 + %temp1 = call i32 @strcmp(i8* %str1, i8* %str2) + ret i32 %temp1 + +} + +; strcmp(x, "") -> *x +define i32 @test2(i8* %str1) { +; CHECK: @test2 +; CHECK: %strcmpload = load i8* %str +; CHECK: %1 = zext i8 %strcmpload to i32 +; CHECK: ret i32 %1 + + %str2 = getelementptr inbounds [1 x i8]* @null, i32 0, i32 0 + %temp1 = call i32 @strcmp(i8* %str1, i8* %str2) + ret i32 %temp1 +} + +; strcmp(x, y) -> cnst +define i32 @test3() { +; CHECK: @test3 +; CHECK: ret i32 -1 + + %str1 = getelementptr inbounds [5 x i8]* @hell, i32 0, i32 0 + %str2 = getelementptr inbounds [6 x i8]* @hello, i32 0, i32 0 + %temp1 = call i32 @strcmp(i8* %str1, i8* %str2) + ret i32 %temp1 +} + +define i32 @test4() { +; CHECK: @test4 +; CHECK: ret i32 1 + + %str1 = getelementptr inbounds [5 x i8]* @hell, i32 0, i32 0 + %str2 = getelementptr inbounds [1 x i8]* @null, i32 0, i32 0 + %temp1 = call i32 @strcmp(i8* %str1, i8* %str2) + ret i32 %temp1 +} + +; strcmp(x, y) -> memcmp(x, y, <known length>) +; (This transform is rather difficult to trigger in a useful manner) +define i32 @test5(i1 %b) { +; CHECK: @test5 +; CHECK: %memcmp = call i32 @memcmp(i8* getelementptr inbounds ([6 x i8]* @hello, i32 0, i32 0), i8* %str2, i32 5) +; CHECK: ret i32 %memcmp + + %str1 = getelementptr inbounds [6 x i8]* @hello, i32 0, i32 0 + %temp1 = getelementptr inbounds [5 x i8]* @hell, i32 0, i32 0 + %temp2 = getelementptr inbounds [5 x i8]* @bell, i32 0, i32 0 + %str2 = select i1 %b, i8* %temp1, i8* %temp2 + %temp3 = call i32 @strcmp(i8* %str1, i8* %str2) + ret i32 %temp3 +} + +; strcmp(x,x) -> 0 +define i32 @test6(i8* %str) { +; CHECK: @test6 +; CHECK: ret i32 0 + + %temp1 = call i32 @strcmp(i8* %str, i8* %str) + ret i32 %temp1 +} diff --git a/test/Transforms/InstCombine/strcmp-2.ll b/test/Transforms/InstCombine/strcmp-2.ll new file mode 100644 index 0000000..2051896 --- /dev/null +++ b/test/Transforms/InstCombine/strcmp-2.ll @@ -0,0 +1,20 @@ +; Test that the strcmp library call simplifier works correctly. +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" +@hell = constant [5 x i8] c"hell\00" + +declare i16 @strcmp(i8*, i8*) + +define i16 @test_nosimplify() { +; CHECK: @test_nosimplify +; CHECK: call i16 @strcmp +; CHECK: ret i16 %temp1 + + %str1 = getelementptr inbounds [5 x i8]* @hell, i32 0, i32 0 + %str2 = getelementptr inbounds [6 x i8]* @hello, i32 0, i32 0 + %temp1 = call i16 @strcmp(i8* %str1, i8* %str2) + ret i16 %temp1 +} diff --git a/test/Transforms/InstCombine/strcpy-1.ll b/test/Transforms/InstCombine/strcpy-1.ll new file mode 100644 index 0000000..b6cf048 --- /dev/null +++ b/test/Transforms/InstCombine/strcpy-1.ll @@ -0,0 +1,45 @@ +; Test that the strcpy library call simplifier works correctly. +; rdar://6839935 +; RUN: opt < %s -instcombine -S | FileCheck %s +; +; This transformation requires the pointer size, as it assumes that size_t is +; the size of a pointer. +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" + +@hello = constant [6 x i8] c"hello\00" +@a = common global [32 x i8] zeroinitializer, align 1 +@b = common global [32 x i8] zeroinitializer, align 1 + +declare i8* @strcpy(i8*, i8*) + +define void @test_simplify1() { +; CHECK: @test_simplify1 + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + + call i8* @strcpy(i8* %dst, i8* %src) +; CHECK: @llvm.memcpy.p0i8.p0i8.i32 + ret void +} + +define i8* @test_simplify2() { +; CHECK: @test_simplify2 + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + + %ret = call i8* @strcpy(i8* %dst, i8* %dst) +; CHECK: ret i8* getelementptr inbounds ([32 x i8]* @a, i32 0, i32 0) + ret i8* %ret +} + +define i8* @test_no_simplify1() { +; CHECK: @test_no_simplify1 + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [32 x i8]* @b, i32 0, i32 0 + + %ret = call i8* @strcpy(i8* %dst, i8* %src) +; CHECK: call i8* @strcpy + ret i8* %ret +} diff --git a/test/Transforms/InstCombine/strcpy-2.ll b/test/Transforms/InstCombine/strcpy-2.ll new file mode 100644 index 0000000..779e9fd --- /dev/null +++ b/test/Transforms/InstCombine/strcpy-2.ll @@ -0,0 +1,22 @@ +; Test that the strcpy library call simplifier works correctly. +; RUN: opt < %s -instcombine -S | FileCheck %s +; +; This transformation requires the pointer size, as it assumes that size_t is +; the size of a pointer. +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" + +@hello = constant [6 x i8] c"hello\00" +@a = common global [32 x i8] zeroinitializer, align 1 + +declare i16* @strcpy(i8*, i8*) + +define void @test_no_simplify1() { +; CHECK: @test_no_simplify1 + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + + call i16* @strcpy(i8* %dst, i8* %src) +; CHECK: call i16* @strcpy + ret void +} diff --git a/test/Transforms/InstCombine/strcpy_chk-1.ll b/test/Transforms/InstCombine/strcpy_chk-1.ll new file mode 100644 index 0000000..3e48f4f --- /dev/null +++ b/test/Transforms/InstCombine/strcpy_chk-1.ll @@ -0,0 +1,94 @@ +; Test lib call simplification of __strcpy_chk calls with various values +; for src, dst, and slen. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@a = common global [60 x i8] zeroinitializer, align 1 +@b = common global [60 x i8] zeroinitializer, align 1 +@.str = private constant [12 x i8] c"abcdefghijk\00" + +; Check cases where slen >= strlen (src). + +define void @test_simplify1() { +; CHECK: @test_simplify1 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [12 x i8]* @.str, i32 0, i32 0 + +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32 + call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 60) + ret void +} + +define void @test_simplify2() { +; CHECK: @test_simplify2 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [12 x i8]* @.str, i32 0, i32 0 + +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32 + call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 12) + ret void +} + +define void @test_simplify3() { +; CHECK: @test_simplify3 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [12 x i8]* @.str, i32 0, i32 0 + +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32 + call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 -1) + ret void +} + +; Check cases where there are no string constants. + +define void @test_simplify4() { +; CHECK: @test_simplify4 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [60 x i8]* @b, i32 0, i32 0 + +; CHECK-NEXT: call i8* @strcpy + call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 -1) + ret void +} + +; Check case where the string length is not constant. + +define void @test_simplify5() { +; CHECK: @test_simplify5 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [12 x i8]* @.str, i32 0, i32 0 + +; CHECK: @__memcpy_chk + %len = call i32 @llvm.objectsize.i32(i8* %dst, i1 false) + call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 %len) + ret void +} + +; Check case where the source and destination are the same. + +define i8* @test_simplify6() { +; CHECK: @test_simplify6 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + +; CHECK: getelementptr inbounds ([60 x i8]* @a, i32 0, i32 0) + %len = call i32 @llvm.objectsize.i32(i8* %dst, i1 false) + %ret = call i8* @__strcpy_chk(i8* %dst, i8* %dst, i32 %len) + ret i8* %ret +} + +; Check case where slen < strlen (src). + +define void @test_no_simplify1() { +; CHECK: @test_no_simplify1 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [60 x i8]* @b, i32 0, i32 0 + +; CHECK-NEXT: call i8* @__strcpy_chk + call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 8) + ret void +} + +declare i8* @__strcpy_chk(i8*, i8*, i32) nounwind +declare i32 @llvm.objectsize.i32(i8*, i1) nounwind readonly diff --git a/test/Transforms/InstCombine/strcpy_chk-2.ll b/test/Transforms/InstCombine/strcpy_chk-2.ll new file mode 100644 index 0000000..d76ea5d --- /dev/null +++ b/test/Transforms/InstCombine/strcpy_chk-2.ll @@ -0,0 +1,21 @@ +; Test that lib call simplification doesn't simplify __strcpy_chk calls +; with the wrong prototype. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@a = common global [60 x i16] zeroinitializer, align 1 +@.str = private constant [8 x i8] c"abcdefg\00" + +define void @test_no_simplify() { +; CHECK: @test_no_simplify + %dst = getelementptr inbounds [60 x i16]* @a, i32 0, i32 0 + %src = getelementptr inbounds [8 x i8]* @.str, i32 0, i32 0 + +; CHECK-NEXT: call i16* @__strcpy_chk + call i16* @__strcpy_chk(i16* %dst, i8* %src, i32 8) + ret void +} + +declare i16* @__strcpy_chk(i16*, i8*, i32) diff --git a/test/Transforms/InstCombine/strcpy_chk.ll b/test/Transforms/InstCombine/strcpy_chk.ll deleted file mode 100644 index 8835a0b..0000000 --- a/test/Transforms/InstCombine/strcpy_chk.ll +++ /dev/null @@ -1,13 +0,0 @@ -; RUN: opt < %s -instcombine -S | FileCheck %s -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" -@a = common global [60 x i8] zeroinitializer, align 1 ; <[60 x i8]*> [#uses=1] -@.str = private constant [8 x i8] c"abcdefg\00" ; <[8 x i8]*> [#uses=1] - -define i8* @foo() nounwind { -; CHECK: @foo -; CHECK-NEXT: call i8* @strcpy - %call = call i8* @__strcpy_chk(i8* getelementptr inbounds ([60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @.str, i32 0, i32 0), i32 60) ; <i8*> [#uses=1] - ret i8* %call -} - -declare i8* @__strcpy_chk(i8*, i8*, i32) nounwind diff --git a/test/Transforms/InstCombine/strcspn-1.ll b/test/Transforms/InstCombine/strcspn-1.ll new file mode 100644 index 0000000..60fad89 --- /dev/null +++ b/test/Transforms/InstCombine/strcspn-1.ll @@ -0,0 +1,57 @@ +; Test that the strcspn library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +@abcba = constant [6 x i8] c"abcba\00" +@abc = constant [4 x i8] c"abc\00" +@null = constant [1 x i8] zeroinitializer + +declare i64 @strcspn(i8*, i8*) + +; Check strcspn(s, "") -> strlen(s). + +define i64 @test_simplify1(i8* %str) { +; CHECK: @test_simplify1 + %pat = getelementptr [1 x i8]* @null, i32 0, i32 0 + + %ret = call i64 @strcspn(i8* %str, i8* %pat) +; CHECK-NEXT: [[VAR:%[a-z]+]] = call i64 @strlen(i8* %str) + ret i64 %ret +; CHECK-NEXT: ret i64 [[VAR]] +} + +; Check strcspn("", s) -> 0. + +define i64 @test_simplify2(i8* %pat) { +; CHECK: @test_simplify2 + %str = getelementptr [1 x i8]* @null, i32 0, i32 0 + + %ret = call i64 @strcspn(i8* %str, i8* %pat) + ret i64 %ret +; CHECK-NEXT: ret i64 0 +} + +; Check strcspn(s1, s2), where s1 and s2 are constants. + +define i64 @test_simplify3() { +; CHECK: @test_simplify3 + %str = getelementptr [6 x i8]* @abcba, i32 0, i32 0 + %pat = getelementptr [4 x i8]* @abc, i32 0, i32 0 + + %ret = call i64 @strcspn(i8* %str, i8* %pat) + ret i64 %ret +; CHECK-NEXT: ret i64 0 +} + +; Check cases that shouldn't be simplified. + +define i64 @test_no_simplify1(i8* %str, i8* %pat) { +; CHECK: @test_no_simplify1 + + %ret = call i64 @strcspn(i8* %str, i8* %pat) +; CHECK-NEXT: %ret = call i64 @strcspn(i8* %str, i8* %pat) + ret i64 %ret +; CHECK-NEXT: ret i64 %ret +} diff --git a/test/Transforms/InstCombine/strcspn-2.ll b/test/Transforms/InstCombine/strcspn-2.ll new file mode 100644 index 0000000..4e23936 --- /dev/null +++ b/test/Transforms/InstCombine/strcspn-2.ll @@ -0,0 +1,21 @@ +; Test that the strcspn library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +@null = constant [1 x i8] zeroinitializer + +declare double @strcspn(i8*, i8*) + +; Check that strcspn functions with the wrong prototype aren't simplified. + +define double @test_no_simplify1(i8* %pat) { +; CHECK: @test_no_simplify1 + %str = getelementptr [1 x i8]* @null, i32 0, i32 0 + + %ret = call double @strcspn(i8* %str, i8* %pat) +; CHECK-NEXT: call double @strcspn + ret double %ret +; CHECK-NEXT: ret double %ret +} diff --git a/test/Transforms/InstCombine/strlen-1.ll b/test/Transforms/InstCombine/strlen-1.ll new file mode 100644 index 0000000..6d7464a --- /dev/null +++ b/test/Transforms/InstCombine/strlen-1.ll @@ -0,0 +1,97 @@ +; Test that the strlen library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" +@null = constant [1 x i8] zeroinitializer +@null_hello = constant [7 x i8] c"\00hello\00" +@nullstring = constant i8 0 +@a = common global [32 x i8] zeroinitializer, align 1 + +declare i32 @strlen(i8*) + +; Check strlen(string constant) -> integer constant. + +define i32 @test_simplify1() { +; CHECK: @test_simplify1 + %hello_p = getelementptr [6 x i8]* @hello, i32 0, i32 0 + %hello_l = call i32 @strlen(i8* %hello_p) + ret i32 %hello_l +; CHECK-NEXT: ret i32 5 +} + +define i32 @test_simplify2() { +; CHECK: @test_simplify2 + %null_p = getelementptr [1 x i8]* @null, i32 0, i32 0 + %null_l = call i32 @strlen(i8* %null_p) + ret i32 %null_l +; CHECK-NEXT: ret i32 0 +} + +define i32 @test_simplify3() { +; CHECK: @test_simplify3 + %null_hello_p = getelementptr [7 x i8]* @null_hello, i32 0, i32 0 + %null_hello_l = call i32 @strlen(i8* %null_hello_p) + ret i32 %null_hello_l +; CHECK-NEXT: ret i32 0 +} + +define i32 @test_simplify4() { +; CHECK: @test_simplify4 + %len = tail call i32 @strlen(i8* @nullstring) nounwind + ret i32 %len +; CHECK-NEXT: ret i32 0 +} + +; Check strlen(x) == 0 --> *x == 0. + +define i1 @test_simplify5() { +; CHECK: @test_simplify5 + %hello_p = getelementptr [6 x i8]* @hello, i32 0, i32 0 + %hello_l = call i32 @strlen(i8* %hello_p) + %eq_hello = icmp eq i32 %hello_l, 0 + ret i1 %eq_hello +; CHECK-NEXT: ret i1 false +} + +define i1 @test_simplify6() { +; CHECK: @test_simplify6 + %null_p = getelementptr [1 x i8]* @null, i32 0, i32 0 + %null_l = call i32 @strlen(i8* %null_p) + %eq_null = icmp eq i32 %null_l, 0 + ret i1 %eq_null +; CHECK-NEXT: ret i1 true +} + +; Check strlen(x) != 0 --> *x != 0. + +define i1 @test_simplify7() { +; CHECK: @test_simplify7 + %hello_p = getelementptr [6 x i8]* @hello, i32 0, i32 0 + %hello_l = call i32 @strlen(i8* %hello_p) + %ne_hello = icmp ne i32 %hello_l, 0 + ret i1 %ne_hello +; CHECK-NEXT: ret i1 true +} + +define i1 @test_simplify8() { +; CHECK: @test_simplify8 + %null_p = getelementptr [1 x i8]* @null, i32 0, i32 0 + %null_l = call i32 @strlen(i8* %null_p) + %ne_null = icmp ne i32 %null_l, 0 + ret i1 %ne_null +; CHECK-NEXT: ret i1 false +} + +; Check cases that shouldn't be simplified. + +define i32 @test_no_simplify1() { +; CHECK: @test_no_simplify1 + %a_p = getelementptr [32 x i8]* @a, i32 0, i32 0 + %a_l = call i32 @strlen(i8* %a_p) +; CHECK-NEXT: %a_l = call i32 @strlen + ret i32 %a_l +; CHECK-NEXT: ret i32 %a_l +} diff --git a/test/Transforms/InstCombine/strlen-2.ll b/test/Transforms/InstCombine/strlen-2.ll new file mode 100644 index 0000000..c4fd54c --- /dev/null +++ b/test/Transforms/InstCombine/strlen-2.ll @@ -0,0 +1,18 @@ +; Test that the strlen library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" + +declare i32 @strlen(i8*, i32) + +define i32 @test_no_simplify1() { +; CHECK: @test_no_simplify1 + %hello_p = getelementptr [6 x i8]* @hello, i32 0, i32 0 + %hello_l = call i32 @strlen(i8* %hello_p, i32 187) +; CHECK-NEXT: %hello_l = call i32 @strlen + ret i32 %hello_l +; CHECK-NEXT: ret i32 %hello_l +} diff --git a/test/Transforms/InstCombine/strncat-1.ll b/test/Transforms/InstCombine/strncat-1.ll new file mode 100644 index 0000000..ad2a18b --- /dev/null +++ b/test/Transforms/InstCombine/strncat-1.ll @@ -0,0 +1,37 @@ +; Test that the strncat libcall simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" +@null = constant [1 x i8] zeroinitializer +@null_hello = constant [7 x i8] c"\00hello\00" + +declare i8* @strncat(i8*, i8*, i32) +declare i32 @puts(i8*) + +define i32 @main() { +; CHECK: @main +; CHECK-NOT: call i8* @strncat +; CHECK: call i32 @puts + + %target = alloca [1024 x i8] + %arg1 = getelementptr [1024 x i8]* %target, i32 0, i32 0 + store i8 0, i8* %arg1 + + ; rslt1 = strncat(target, "hello\00") + %arg2 = getelementptr [6 x i8]* @hello, i32 0, i32 0 + %rslt1 = call i8* @strncat(i8* %arg1, i8* %arg2, i32 6) + + ; rslt2 = strncat(rslt1, "\00") + %arg3 = getelementptr [1 x i8]* @null, i32 0, i32 0 + %rslt2 = call i8* @strncat(i8* %rslt1, i8* %arg3, i32 42) + + ; rslt3 = strncat(rslt2, "\00hello\00") + %arg4 = getelementptr [7 x i8]* @null_hello, i32 0, i32 0 + %rslt3 = call i8* @strncat(i8* %rslt2, i8* %arg4, i32 42) + + call i32 @puts(i8* %rslt3) + ret i32 0 +} diff --git a/test/Transforms/InstCombine/strncat-2.ll b/test/Transforms/InstCombine/strncat-2.ll new file mode 100644 index 0000000..c56deac --- /dev/null +++ b/test/Transforms/InstCombine/strncat-2.ll @@ -0,0 +1,53 @@ +; Test that the strncat libcall simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" +@empty = constant [1 x i8] c"\00" +@a = common global [32 x i8] zeroinitializer, align 1 + +declare i8* @strncat(i8*, i8*, i32) + +define void @test_simplify1() { +; CHECK: @test_simplify1 +; CHECK-NOT: call i8* @strncat +; CHECK: ret void + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + call i8* @strncat(i8* %dst, i8* %src, i32 13) + ret void +} + +define void @test_simplify2() { +; CHECK: @test_simplify2 +; CHECK-NEXT: ret void + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [1 x i8]* @empty, i32 0, i32 0 + call i8* @strncat(i8* %dst, i8* %src, i32 13) + ret void +} + +define void @test_simplify3() { +; CHECK: @test_simplify3 +; CHECK-NEXT: ret void + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + call i8* @strncat(i8* %dst, i8* %src, i32 0) + ret void +} + +define void @test_nosimplify1() { +; CHECK: @test_nosimplify1 +; CHECK: call i8* @strncat +; CHECK: ret void + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + call i8* @strncat(i8* %dst, i8* %src, i32 1) + ret void +} diff --git a/test/Transforms/InstCombine/strncat-3.ll b/test/Transforms/InstCombine/strncat-3.ll new file mode 100644 index 0000000..3cd7971 --- /dev/null +++ b/test/Transforms/InstCombine/strncat-3.ll @@ -0,0 +1,22 @@ +; Test that the strncat libcall simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" +@empty = constant [1 x i8] c"\00" +@a = common global [32 x i8] zeroinitializer, align 1 + +declare i16* @strncat(i8*, i8*, i32) + +define void @test_nosimplify1() { +; CHECK: @test_nosimplify1 +; CHECK: call i16* @strncat +; CHECK: ret void + + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + call i16* @strncat(i8* %dst, i8* %src, i32 13) + ret void +} diff --git a/test/Transforms/InstCombine/strncmp-1.ll b/test/Transforms/InstCombine/strncmp-1.ll new file mode 100644 index 0000000..187c2fa --- /dev/null +++ b/test/Transforms/InstCombine/strncmp-1.ll @@ -0,0 +1,99 @@ +; Test that the strncmp library call simplifier works correctly. +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" +@hell = constant [5 x i8] c"hell\00" +@bell = constant [5 x i8] c"bell\00" +@null = constant [1 x i8] zeroinitializer + +declare i32 @strncmp(i8*, i8*, i32) + +; strncmp("", x, n) -> -*x +define i32 @test1(i8* %str2) { +; CHECK: @test1 +; CHECK: %strcmpload = load i8* %str +; CHECK: %1 = zext i8 %strcmpload to i32 +; CHECK: %2 = sub i32 0, %1 +; CHECK: ret i32 %2 + + %str1 = getelementptr inbounds [1 x i8]* @null, i32 0, i32 0 + %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 10) + ret i32 %temp1 +} + +; strncmp(x, "", n) -> *x +define i32 @test2(i8* %str1) { +; CHECK: @test2 +; CHECK: %strcmpload = load i8* %str1 +; CHECK: %1 = zext i8 %strcmpload to i32 +; CHECK: ret i32 %1 + + %str2 = getelementptr inbounds [1 x i8]* @null, i32 0, i32 0 + %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 10) + ret i32 %temp1 +} + +; strncmp(x, y, n) -> cnst +define i32 @test3() { +; CHECK: @test3 +; CHECK: ret i32 -1 + + %str1 = getelementptr inbounds [5 x i8]* @hell, i32 0, i32 0 + %str2 = getelementptr inbounds [6 x i8]* @hello, i32 0, i32 0 + %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 10) + ret i32 %temp1 +} + +define i32 @test4() { +; CHECK: @test4 +; CHECK: ret i32 1 + + %str1 = getelementptr inbounds [5 x i8]* @hell, i32 0, i32 0 + %str2 = getelementptr inbounds [1 x i8]* @null, i32 0, i32 0 + %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 10) + ret i32 %temp1 +} + +define i32 @test5() { +; CHECK: @test5 +; CHECK: ret i32 0 + + %str1 = getelementptr inbounds [5 x i8]* @hell, i32 0, i32 0 + %str2 = getelementptr inbounds [6 x i8]* @hello, i32 0, i32 0 + %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 4) + ret i32 %temp1 +} + +; strncmp(x,y,1) -> memcmp(x,y,1) +define i32 @test6(i8* %str1, i8* %str2) { +; CHECK: @test6 +; CHECK: [[LOAD1:%[a-z]+]] = load i8* %str1, align 1 +; CHECK: [[ZEXT1:%[a-z]+]] = zext i8 [[LOAD1]] to i32 +; CHECK: [[LOAD2:%[a-z]+]] = load i8* %str2, align 1 +; CHECK: [[ZEXT2:%[a-z]+]] = zext i8 [[LOAD2]] to i32 +; CHECK: [[RET:%[a-z]+]] = sub i32 [[ZEXT1]], [[ZEXT2]] +; CHECK: ret i32 [[RET]] + + %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 1) + ret i32 %temp1 +} + +; strncmp(x,y,0) -> 0 +define i32 @test7(i8* %str1, i8* %str2) { +; CHECK: @test7 +; CHECK: ret i32 0 + + %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 0) + ret i32 %temp1 +} + +; strncmp(x,x,n) -> 0 +define i32 @test8(i8* %str, i32 %n) { +; CHECK: @test8 +; CHECK: ret i32 0 + + %temp1 = call i32 @strncmp(i8* %str, i8* %str, i32 %n) + ret i32 %temp1 +} diff --git a/test/Transforms/InstCombine/strncmp-2.ll b/test/Transforms/InstCombine/strncmp-2.ll new file mode 100644 index 0000000..3fc43a6 --- /dev/null +++ b/test/Transforms/InstCombine/strncmp-2.ll @@ -0,0 +1,20 @@ +; Test that the strncmp library call simplifier works correctly. +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" +@hell = constant [5 x i8] c"hell\00" + +declare i16 @strncmp(i8*, i8*, i32) + +define i16 @test_nosimplify() { +; CHECK: @test_nosimplify +; CHECK: call i16 @strncmp +; CHECK: ret i16 %temp1 + + %str1 = getelementptr inbounds [5 x i8]* @hell, i32 0, i32 0 + %str2 = getelementptr inbounds [6 x i8]* @hello, i32 0, i32 0 + %temp1 = call i16 @strncmp(i8* %str1, i8* %str2, i32 10) + ret i16 %temp1 +} diff --git a/test/Transforms/InstCombine/strncpy-1.ll b/test/Transforms/InstCombine/strncpy-1.ll new file mode 100644 index 0000000..3ce2b9b --- /dev/null +++ b/test/Transforms/InstCombine/strncpy-1.ll @@ -0,0 +1,95 @@ +; Test that the strncpy library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" +@null = constant [1 x i8] zeroinitializer +@null_hello = constant [7 x i8] c"\00hello\00" +@a = common global [32 x i8] zeroinitializer, align 1 +@b = common global [32 x i8] zeroinitializer, align 1 + +declare i8* @strncpy(i8*, i8*, i32) +declare i32 @puts(i8*) + +; Check a bunch of strncpy invocations together. + +define i32 @test_simplify1() { +; CHECK: @test_simplify1 +; CHECK-NOT: call i8* @strncpy +; CHECK: call i32 @puts + %target = alloca [1024 x i8] + %arg1 = getelementptr [1024 x i8]* %target, i32 0, i32 0 + store i8 0, i8* %arg1 + + %arg2 = getelementptr [6 x i8]* @hello, i32 0, i32 0 + %rslt1 = call i8* @strncpy(i8* %arg1, i8* %arg2, i32 6) + + %arg3 = getelementptr [1 x i8]* @null, i32 0, i32 0 + %rslt2 = call i8* @strncpy(i8* %rslt1, i8* %arg3, i32 42) + + %arg4 = getelementptr [7 x i8]* @null_hello, i32 0, i32 0 + %rslt3 = call i8* @strncpy(i8* %rslt2, i8* %arg4, i32 42) + + call i32 @puts( i8* %rslt3 ) + ret i32 0 +} + +; Check strncpy(x, "", y) -> memset(x, '\0', y, 1). + +define void @test_simplify2() { +; CHECK: @test_simplify2 + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [1 x i8]* @null, i32 0, i32 0 + + call i8* @strncpy(i8* %dst, i8* %src, i32 32) +; CHECK: call void @llvm.memset.p0i8.i32 + ret void +} + +; Check strncpy(x, y, 0) -> x. + +define i8* @test_simplify3() { +; CHECK: @test_simplify3 + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + + %ret = call i8* @strncpy(i8* %dst, i8* %src, i32 0) + ret i8* %ret +; CHECK: ret i8* getelementptr inbounds ([32 x i8]* @a, i32 0, i32 0) +} + +; Check strncpy(x, s, c) -> memcpy(x, s, c, 1) [s and c are constant]. + +define void @test_simplify4() { +; CHECK: @test_simplify4 + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + + call i8* @strncpy(i8* %dst, i8* %src, i32 6) +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32 + ret void +} + +; Check cases that shouldn't be simplified. + +define void @test_no_simplify1() { +; CHECK: @test_no_simplify1 + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [32 x i8]* @b, i32 0, i32 0 + + call i8* @strncpy(i8* %dst, i8* %src, i32 32) +; CHECK: call i8* @strncpy + ret void +} + +define void @test_no_simplify2() { +; CHECK: @test_no_simplify2 + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + + call i8* @strncpy(i8* %dst, i8* %src, i32 8) +; CHECK: call i8* @strncpy + ret void +} diff --git a/test/Transforms/InstCombine/strncpy-2.ll b/test/Transforms/InstCombine/strncpy-2.ll new file mode 100644 index 0000000..ac28ea6 --- /dev/null +++ b/test/Transforms/InstCombine/strncpy-2.ll @@ -0,0 +1,22 @@ +; Test that the strncpy library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [6 x i8] c"hello\00" +@a = common global [32 x i8] zeroinitializer, align 1 + +declare i16* @strncpy(i8*, i8*, i32) + +; Check that 'strncpy' functions with the wrong prototype aren't simplified. + +define void @test_no_simplify1() { +; CHECK: @test_no_simplify1 + %dst = getelementptr [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8]* @hello, i32 0, i32 0 + + call i16* @strncpy(i8* %dst, i8* %src, i32 6) +; CHECK: call i16* @strncpy + ret void +} diff --git a/test/Transforms/InstCombine/strncpy_chk-1.ll b/test/Transforms/InstCombine/strncpy_chk-1.ll new file mode 100644 index 0000000..aadff42 --- /dev/null +++ b/test/Transforms/InstCombine/strncpy_chk-1.ll @@ -0,0 +1,66 @@ +; Test lib call simplification of __strncpy_chk calls with various values +; for len and dstlen. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@a = common global [60 x i8] zeroinitializer, align 1 +@b = common global [60 x i8] zeroinitializer, align 1 +@.str = private constant [12 x i8] c"abcdefghijk\00" + +; Check cases where dstlen >= len + +define void @test_simplify1() { +; CHECK: @test_simplify1 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [12 x i8]* @.str, i32 0, i32 0 + +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32 + call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 12, i32 60) + ret void +} + +define void @test_simplify2() { +; CHECK: @test_simplify2 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [12 x i8]* @.str, i32 0, i32 0 + +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32 + call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 12, i32 12) + ret void +} + +define void @test_simplify3() { +; CHECK: @test_simplify3 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [60 x i8]* @b, i32 0, i32 0 + +; CHECK-NEXT: call i8* @strncpy + call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 12, i32 60) + ret void +} + +; Check cases where dstlen < len + +define void @test_no_simplify1() { +; CHECK: @test_no_simplify1 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [12 x i8]* @.str, i32 0, i32 0 + +; CHECK-NEXT: call i8* @__strncpy_chk + call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 8, i32 4) + ret void +} + +define void @test_no_simplify2() { +; CHECK: @test_no_simplify2 + %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 + %src = getelementptr inbounds [60 x i8]* @b, i32 0, i32 0 + +; CHECK-NEXT: call i8* @__strncpy_chk + call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 8, i32 0) + ret void +} + +declare i8* @__strncpy_chk(i8*, i8*, i32, i32) diff --git a/test/Transforms/InstCombine/strncpy_chk-2.ll b/test/Transforms/InstCombine/strncpy_chk-2.ll new file mode 100644 index 0000000..a0f132e --- /dev/null +++ b/test/Transforms/InstCombine/strncpy_chk-2.ll @@ -0,0 +1,21 @@ +; Test that lib call simplification doesn't simplify __strncpy_chk calls +; with the wrong prototype. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@a = common global [60 x i16] zeroinitializer, align 1 +@b = common global [60 x i16] zeroinitializer, align 1 + +define void @test_no_simplify() { +; CHECK: @test_no_simplify + %dst = getelementptr inbounds [60 x i16]* @a, i32 0, i32 0 + %src = getelementptr inbounds [60 x i16]* @b, i32 0, i32 0 + +; CHECK-NEXT: call i16* @__strncpy_chk + call i16* @__strncpy_chk(i16* %dst, i16* %src, i32 60, i32 60) + ret void +} + +declare i16* @__strncpy_chk(i16*, i16*, i32, i32) diff --git a/test/Transforms/InstCombine/strpbrk-1.ll b/test/Transforms/InstCombine/strpbrk-1.ll new file mode 100644 index 0000000..a5d0d86 --- /dev/null +++ b/test/Transforms/InstCombine/strpbrk-1.ll @@ -0,0 +1,68 @@ +; Test that the strpbrk library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [12 x i8] c"hello world\00" +@w = constant [2 x i8] c"w\00" +@null = constant [1 x i8] zeroinitializer + +declare i8* @strpbrk(i8*, i8*) + +; Check strpbrk(s, "") -> NULL. + +define i8* @test_simplify1(i8* %str) { +; CHECK: @test_simplify1 + %pat = getelementptr [1 x i8]* @null, i32 0, i32 0 + + %ret = call i8* @strpbrk(i8* %str, i8* %pat) + ret i8* %ret +; CHECK-NEXT: ret i8* null +} + +; Check strpbrk("", s) -> NULL. + +define i8* @test_simplify2(i8* %pat) { +; CHECK: @test_simplify2 + %str = getelementptr [1 x i8]* @null, i32 0, i32 0 + + %ret = call i8* @strpbrk(i8* %str, i8* %pat) + ret i8* %ret +; CHECK-NEXT: ret i8* null +} + +; Check strpbrk(s1, s2), where s1 and s2 are constants. + +define i8* @test_simplify3() { +; CHECK: @test_simplify3 + %str = getelementptr [12 x i8]* @hello, i32 0, i32 0 + %pat = getelementptr [2 x i8]* @w, i32 0, i32 0 + + %ret = call i8* @strpbrk(i8* %str, i8* %pat) + ret i8* %ret +; CHECK-NEXT: ret i8* getelementptr inbounds ([12 x i8]* @hello, i32 0, i32 6) +} + +; Check strpbrk(s, "a") -> strchr(s, 'a'). + +define i8* @test_simplify4(i8* %str) { +; CHECK: @test_simplify4 + %pat = getelementptr [2 x i8]* @w, i32 0, i32 0 + + %ret = call i8* @strpbrk(i8* %str, i8* %pat) +; CHECK-NEXT: [[VAR:%[a-z]+]] = call i8* @strchr(i8* %str, i32 119) + ret i8* %ret +; CHECK-NEXT: ret i8* [[VAR]] +} + +; Check cases that shouldn't be simplified. + +define i8* @test_no_simplify1(i8* %str, i8* %pat) { +; CHECK: @test_no_simplify1 + + %ret = call i8* @strpbrk(i8* %str, i8* %pat) +; CHECK-NEXT: %ret = call i8* @strpbrk(i8* %str, i8* %pat) + ret i8* %ret +; CHECK-NEXT: ret i8* %ret +} diff --git a/test/Transforms/InstCombine/strpbrk-2.ll b/test/Transforms/InstCombine/strpbrk-2.ll new file mode 100644 index 0000000..31ac290 --- /dev/null +++ b/test/Transforms/InstCombine/strpbrk-2.ll @@ -0,0 +1,23 @@ +; Test that the strpbrk library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [12 x i8] c"hello world\00" +@w = constant [2 x i8] c"w\00" + +declare i16* @strpbrk(i8*, i8*) + +; Check that 'strpbrk' functions with the wrong prototype aren't simplified. + +define i16* @test_no_simplify1() { +; CHECK: @test_no_simplify1 + %str = getelementptr [12 x i8]* @hello, i32 0, i32 0 + %pat = getelementptr [2 x i8]* @w, i32 0, i32 0 + + %ret = call i16* @strpbrk(i8* %str, i8* %pat) +; CHECK-NEXT: %ret = call i16* @strpbrk + ret i16* %ret +; CHECK-NEXT: ret i16* %ret +} diff --git a/test/Transforms/InstCombine/strrchr-1.ll b/test/Transforms/InstCombine/strrchr-1.ll new file mode 100644 index 0000000..854ce45 --- /dev/null +++ b/test/Transforms/InstCombine/strrchr-1.ll @@ -0,0 +1,54 @@ +; Test that the strrchr library call simplifier works correctly. +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [14 x i8] c"hello world\5Cn\00" +@null = constant [1 x i8] zeroinitializer +@chp = global i8* zeroinitializer + +declare i8* @strrchr(i8*, i32) + +define void @test_simplify1() { +; CHECK: store i8* getelementptr inbounds ([14 x i8]* @hello, i32 0, i32 6) +; CHECK-NOT: call i8* @strrchr +; CHECK: ret void + + %str = getelementptr [14 x i8]* @hello, i32 0, i32 0 + %dst = call i8* @strrchr(i8* %str, i32 119) + store i8* %dst, i8** @chp + ret void +} + +define void @test_simplify2() { +; CHECK: store i8* null, i8** @chp, align 4 +; CHECK-NOT: call i8* @strrchr +; CHECK: ret void + + %str = getelementptr [1 x i8]* @null, i32 0, i32 0 + %dst = call i8* @strrchr(i8* %str, i32 119) + store i8* %dst, i8** @chp + ret void +} + +define void @test_simplify3() { +; CHECK: store i8* getelementptr inbounds ([14 x i8]* @hello, i32 0, i32 13) +; CHECK-NOT: call i8* @strrchr +; CHECK: ret void + + %src = getelementptr [14 x i8]* @hello, i32 0, i32 0 + %dst = call i8* @strrchr(i8* %src, i32 0) + store i8* %dst, i8** @chp + ret void +} + +define void @test_nosimplify1(i32 %chr) { +; CHECK: @test_nosimplify1 +; CHECK: call i8* @strrchr +; CHECK: ret void + + %src = getelementptr [14 x i8]* @hello, i32 0, i32 0 + %dst = call i8* @strrchr(i8* %src, i32 %chr) + store i8* %dst, i8** @chp + ret void +} diff --git a/test/Transforms/InstCombine/strrchr-2.ll b/test/Transforms/InstCombine/strrchr-2.ll new file mode 100644 index 0000000..1974f6c --- /dev/null +++ b/test/Transforms/InstCombine/strrchr-2.ll @@ -0,0 +1,21 @@ +; Test that the strrchr libcall simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@hello = constant [14 x i8] c"hello world\5Cn\00" +@chr = global i8 zeroinitializer + +declare i8 @strrchr(i8*, i32) + +define void @test_nosimplify1() { +; CHECK: test_nosimplify1 +; CHECK: call i8 @strrchr +; CHECK: ret void + + %str = getelementptr [14 x i8]* @hello, i32 0, i32 0 + %dst = call i8 @strrchr(i8* %str, i32 119) + store i8 %dst, i8* @chr + ret void +} diff --git a/test/Transforms/InstCombine/strspn-1.ll b/test/Transforms/InstCombine/strspn-1.ll new file mode 100644 index 0000000..393f887 --- /dev/null +++ b/test/Transforms/InstCombine/strspn-1.ll @@ -0,0 +1,56 @@ +; Test that the strspn library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +@abcba = constant [6 x i8] c"abcba\00" +@abc = constant [4 x i8] c"abc\00" +@null = constant [1 x i8] zeroinitializer + +declare i64 @strspn(i8*, i8*) + +; Check strspn(s, "") -> 0. + +define i64 @test_simplify1(i8* %str) { +; CHECK: @test_simplify1 + %pat = getelementptr [1 x i8]* @null, i32 0, i32 0 + + %ret = call i64 @strspn(i8* %str, i8* %pat) + ret i64 %ret +; CHECK-NEXT: ret i64 0 +} + +; Check strspn("", s) -> 0. + +define i64 @test_simplify2(i8* %pat) { +; CHECK: @test_simplify2 + %str = getelementptr [1 x i8]* @null, i32 0, i32 0 + + %ret = call i64 @strspn(i8* %str, i8* %pat) + ret i64 %ret +; CHECK-NEXT: ret i64 0 +} + +; Check strspn(s1, s2), where s1 and s2 are constants. + +define i64 @test_simplify3() { +; CHECK: @test_simplify3 + %str = getelementptr [6 x i8]* @abcba, i32 0, i32 0 + %pat = getelementptr [4 x i8]* @abc, i32 0, i32 0 + + %ret = call i64 @strspn(i8* %str, i8* %pat) + ret i64 %ret +; CHECK-NEXT: ret i64 5 +} + +; Check cases that shouldn't be simplified. + +define i64 @test_no_simplify1(i8* %str, i8* %pat) { +; CHECK: @test_no_simplify1 + + %ret = call i64 @strspn(i8* %str, i8* %pat) +; CHECK-NEXT: %ret = call i64 @strspn(i8* %str, i8* %pat) + ret i64 %ret +; CHECK-NEXT: ret i64 %ret +} diff --git a/test/Transforms/InstCombine/strstr-1.ll b/test/Transforms/InstCombine/strstr-1.ll new file mode 100644 index 0000000..81f5271 --- /dev/null +++ b/test/Transforms/InstCombine/strstr-1.ll @@ -0,0 +1,65 @@ +; Test that the strstr library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +@.str = private constant [1 x i8] zeroinitializer +@.str1 = private constant [2 x i8] c"a\00" +@.str2 = private constant [6 x i8] c"abcde\00" +@.str3 = private constant [4 x i8] c"bcd\00" + +declare i8* @strstr(i8*, i8*) + +; Check strstr(str, "") -> str. + +define i8* @test_simplify1(i8* %str) { +; CHECK: @test_simplify1 + %pat = getelementptr inbounds [1 x i8]* @.str, i32 0, i32 0 + %ret = call i8* @strstr(i8* %str, i8* %pat) + ret i8* %ret +; CHECK-NEXT: ret i8* %str +} + +; Check strstr(str, "a") -> strchr(str, 'a'). + +define i8* @test_simplify2(i8* %str) { +; CHECK: @test_simplify2 + %pat = getelementptr inbounds [2 x i8]* @.str1, i32 0, i32 0 + %ret = call i8* @strstr(i8* %str, i8* %pat) + ret i8* %ret +; CHECK-NEXT: @strchr(i8* %str, i32 97) +} + +; Check strstr("abcde", "bcd") -> "abcde" + 1. + +define i8* @test_simplify3() { +; CHECK: @test_simplify3 + %str = getelementptr inbounds [6 x i8]* @.str2, i32 0, i32 0 + %pat = getelementptr inbounds [4 x i8]* @.str3, i32 0, i32 0 + %ret = call i8* @strstr(i8* %str, i8* %pat) + ret i8* %ret +; CHECK-NEXT: getelementptr inbounds ([6 x i8]* @.str2, i64 0, i64 1) +} + +; Check strstr(str, str) -> str. + +define i8* @test_simplify4(i8* %str) { +; CHECK: @test_simplify4 + %ret = call i8* @strstr(i8* %str, i8* %str) + ret i8* %ret +; CHECK-NEXT: ret i8* %str +} + +; Check strstr(str, pat) == str -> strncmp(str, pat, strlen(str)) == 0. + +define i1 @test_simplify5(i8* %str, i8* %pat) { +; CHECK: @test_simplify5 + %ret = call i8* @strstr(i8* %str, i8* %pat) + %cmp = icmp eq i8* %ret, %str + ret i1 %cmp +; CHECK: [[LEN:%[a-z]+]] = call {{i[0-9]+}} @strlen(i8* %pat) +; CHECK: [[NCMP:%[a-z]+]] = call {{i[0-9]+}} @strncmp(i8* %str, i8* %pat, {{i[0-9]+}} [[LEN]]) +; CHECK: icmp eq {{i[0-9]+}} [[NCMP]], 0 +; CHECK: ret i1 +} diff --git a/test/Transforms/InstCombine/strstr-2.ll b/test/Transforms/InstCombine/strstr-2.ll new file mode 100644 index 0000000..5092f9b --- /dev/null +++ b/test/Transforms/InstCombine/strstr-2.ll @@ -0,0 +1,18 @@ +; Test that the strstr library call simplifier works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +@null = private constant [1 x i8] zeroinitializer + +declare i8 @strstr(i8*, i8*) + +define i8 @test_no_simplify1(i8* %str) { +; CHECK: @test_no_simplify1 + %pat = getelementptr inbounds [1 x i8]* @null, i32 0, i32 0 + %ret = call i8 @strstr(i8* %str, i8* %pat) +; CHECK-NEXT: call i8 @strstr + ret i8 %ret +; CHECK-NEXT: ret i8 %ret +} diff --git a/test/Transforms/InstCombine/strto-1.ll b/test/Transforms/InstCombine/strto-1.ll new file mode 100644 index 0000000..16c0c67 --- /dev/null +++ b/test/Transforms/InstCombine/strto-1.ll @@ -0,0 +1,82 @@ +; Test that the strto* library call simplifiers works correctly. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" + +declare i64 @strtol(i8* %s, i8** %endptr, i32 %base) +; CHECK: declare i64 @strtol(i8*, i8**, i32) + +declare double @strtod(i8* %s, i8** %endptr, i32 %base) +; CHECK: declare double @strtod(i8*, i8**, i32) + +declare float @strtof(i8* %s, i8** %endptr, i32 %base) +; CHECK: declare float @strtof(i8*, i8**, i32) + +declare i64 @strtoul(i8* %s, i8** %endptr, i32 %base) +; CHECK: declare i64 @strtoul(i8*, i8**, i32) + +declare i64 @strtoll(i8* %s, i8** %endptr, i32 %base) +; CHECK: declare i64 @strtoll(i8*, i8**, i32) + +declare double @strtold(i8* %s, i8** %endptr) +; CHECK: declare double @strtold(i8*, i8**) + +declare i64 @strtoull(i8* %s, i8** %endptr, i32 %base) +; CHECK: declare i64 @strtoull(i8*, i8**, i32) + +define void @test_simplify1(i8* %x, i8** %endptr) { +; CHECK: @test_simplify1 + call i64 @strtol(i8* %x, i8** null, i32 10) +; CHECK-NEXT: call i64 @strtol(i8* nocapture %x, i8** null, i32 10) + ret void +} + +define void @test_simplify2(i8* %x, i8** %endptr) { +; CHECK: @test_simplify2 + call double @strtod(i8* %x, i8** null, i32 10) +; CHECK-NEXT: call double @strtod(i8* nocapture %x, i8** null, i32 10) + ret void +} + +define void @test_simplify3(i8* %x, i8** %endptr) { +; CHECK: @test_simplify3 + call float @strtof(i8* %x, i8** null, i32 10) +; CHECK-NEXT: call float @strtof(i8* nocapture %x, i8** null, i32 10) + ret void +} + +define void @test_simplify4(i8* %x, i8** %endptr) { +; CHECK: @test_simplify4 + call i64 @strtoul(i8* %x, i8** null, i32 10) +; CHECK-NEXT: call i64 @strtoul(i8* nocapture %x, i8** null, i32 10) + ret void +} + +define void @test_simplify5(i8* %x, i8** %endptr) { +; CHECK: @test_simplify5 + call i64 @strtoll(i8* %x, i8** null, i32 10) +; CHECK-NEXT: call i64 @strtoll(i8* nocapture %x, i8** null, i32 10) + ret void +} + +define void @test_simplify6(i8* %x, i8** %endptr) { +; CHECK: @test_simplify6 + call double @strtold(i8* %x, i8** null) +; CHECK-NEXT: call double @strtold(i8* nocapture %x, i8** null) + ret void +} + +define void @test_simplify7(i8* %x, i8** %endptr) { +; CHECK: @test_simplify7 + call i64 @strtoull(i8* %x, i8** null, i32 10) +; CHECK-NEXT: call i64 @strtoull(i8* nocapture %x, i8** null, i32 10) + ret void +} + +define void @test_no_simplify1(i8* %x, i8** %endptr) { +; CHECK: @test_no_simplify1 + call i64 @strtol(i8* %x, i8** %endptr, i32 10) +; CHECK-NEXT: call i64 @strtol(i8* %x, i8** %endptr, i32 10) + ret void +} diff --git a/test/Transforms/InstCombine/struct-assign-tbaa.ll b/test/Transforms/InstCombine/struct-assign-tbaa.ll new file mode 100644 index 0000000..33a771e --- /dev/null +++ b/test/Transforms/InstCombine/struct-assign-tbaa.ll @@ -0,0 +1,44 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind + +; Verify that instcombine preserves TBAA tags when converting a memcpy into +; a scalar load and store. + +%struct.test1 = type { float } + +; CHECK: @test +; CHECK: %2 = load float* %0, align 4, !tbaa !0 +; CHECK: store float %2, float* %1, align 4, !tbaa !0 +; CHECK: ret +define void @test1(%struct.test1* nocapture %a, %struct.test1* nocapture %b) { +entry: + %0 = bitcast %struct.test1* %a to i8* + %1 = bitcast %struct.test1* %b to i8* + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %1, i64 4, i32 4, i1 false), !tbaa.struct !3 + ret void +} + +%struct.test2 = type { i32 (i8*, i32*, double*)** } + +define i32 (i8*, i32*, double*)*** @test2() { +; CHECK: @test2 +; CHECK-NOT: memcpy +; CHECK: ret + %tmp = alloca %struct.test2, align 8 + %tmp1 = bitcast %struct.test2* %tmp to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp1, i8* undef, i64 8, i32 8, i1 false), !tbaa.struct !4 + %tmp2 = getelementptr %struct.test2* %tmp, i32 0, i32 0 + %tmp3 = load i32 (i8*, i32*, double*)*** %tmp2 + ret i32 (i8*, i32*, double*)*** %tmp2 +} + +; CHECK: !0 = metadata !{metadata !"float", metadata !1} + +!0 = metadata !{metadata !"Simple C/C++ TBAA"} +!1 = metadata !{metadata !"omnipotent char", metadata !0} +!2 = metadata !{metadata !"float", metadata !0} +!3 = metadata !{i64 0, i64 4, metadata !2} +!4 = metadata !{i64 0, i64 8, null} diff --git a/test/Transforms/InstCombine/udiv-simplify-bug-1.ll b/test/Transforms/InstCombine/udiv-simplify-bug-1.ll index d95e8f8..74f2fdd 100644 --- a/test/Transforms/InstCombine/udiv-simplify-bug-1.ll +++ b/test/Transforms/InstCombine/udiv-simplify-bug-1.ll @@ -6,9 +6,9 @@ ; The udiv instructions shouldn't be optimized away, and the ; sext instructions should be optimized to zext. -define i64 @bar(i32 %x) nounwind { +define i64 @bar(i32 %x, i32 %g) nounwind { %y = lshr i32 %x, 30 - %r = udiv i32 %y, 3 + %r = udiv i32 %y, %g %z = sext i32 %r to i64 ret i64 %z } diff --git a/test/Transforms/InstCombine/vec_demanded_elts.ll b/test/Transforms/InstCombine/vec_demanded_elts.ll index 0019a57..2d90750 100644 --- a/test/Transforms/InstCombine/vec_demanded_elts.ll +++ b/test/Transforms/InstCombine/vec_demanded_elts.ll @@ -196,7 +196,7 @@ define <4 x float> @test_select(float %f, float %g) { ; CHECK-NOT: insertelement ; CHECK: %a3 = insertelement <4 x float> %a0, float 3.000000e+00, i32 3 ; CHECK-NOT: insertelement -; CHECK: %ret = select <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x float> %a3, <4 x float> <float undef, float 4.000000e+00, float 5.000000e+00, float undef> +; CHECK: shufflevector <4 x float> %a3, <4 x float> <float undef, float 4.000000e+00, float 5.000000e+00, float undef>, <4 x i32> <i32 0, i32 5, i32 6, i32 3> %a0 = insertelement <4 x float> undef, float %f, i32 0 %a1 = insertelement <4 x float> %a0, float 1.000000e+00, i32 1 %a2 = insertelement <4 x float> %a1, float 2.000000e+00, i32 2 diff --git a/test/Transforms/InstCombine/vec_shuffle.ll b/test/Transforms/InstCombine/vec_shuffle.ll index 8f78c2e..14f5321 100644 --- a/test/Transforms/InstCombine/vec_shuffle.ll +++ b/test/Transforms/InstCombine/vec_shuffle.ll @@ -153,3 +153,46 @@ define <8 x i8> @test12a(<8 x i8> %tmp6, <8 x i8> %tmp2) nounwind { ret <8 x i8> %tmp3 } +; We should form a shuffle out of a select with constant condition. +define <4 x i16> @test13a(<4 x i16> %lhs, <4 x i16> %rhs) { +; CHECK: @test13a +; CHECK-NEXT: shufflevector <4 x i16> %lhs, <4 x i16> %rhs, <4 x i32> <i32 0, i32 5, i32 2, i32 7> +; CHECK-NEXT: ret + %A = select <4 x i1> <i1 true, i1 false, i1 true, i1 false>, + <4 x i16> %lhs, <4 x i16> %rhs + ret <4 x i16> %A +} + +define <4 x i16> @test13b(<4 x i16> %lhs, <4 x i16> %rhs) { +; CHECK: @test13b +; CHECK-NEXT: ret <4 x i16> %lhs + %A = select <4 x i1> <i1 true, i1 undef, i1 true, i1 true>, + <4 x i16> %lhs, <4 x i16> %rhs + ret <4 x i16> %A +} + +define <4 x i16> @test13c(<4 x i16> %lhs, <4 x i16> %rhs) { +; CHECK: @test13c +; CHECK-NEXT: shufflevector <4 x i16> %lhs, <4 x i16> %rhs, <4 x i32> <i32 0, i32 undef, i32 2, i32 7> +; CHECK-NEXT: ret + %A = select <4 x i1> <i1 true, i1 undef, i1 true, i1 false>, + <4 x i16> %lhs, <4 x i16> %rhs + ret <4 x i16> %A +} + +define <4 x i16> @test13d(<4 x i16> %lhs, <4 x i16> %rhs) { +; CHECK: @test13d +; CHECK: select +; CHECK-NEXT: ret + %A = select <4 x i1> <i1 true, i1 icmp ugt (<4 x i16>(<4 x i16>, <4 x i16>)* @test13a, <4 x i16>(<4 x i16>, <4 x i16>)* @test13b), i1 true, i1 false>, + <4 x i16> %lhs, <4 x i16> %rhs + ret <4 x i16> %A +} + +define <4 x i16> @test13e(<4 x i16> %lhs, <4 x i16> %rhs) { +; CHECK: @test13e +; CHECK-NEXT: ret <4 x i16> %rhs + %A = select <4 x i1> <i1 false, i1 false, i1 false, i1 false>, + <4 x i16> %lhs, <4 x i16> %rhs + ret <4 x i16> %A +} diff --git a/test/Transforms/InstCombine/vector_gep2.ll b/test/Transforms/InstCombine/vector_gep2.ll new file mode 100644 index 0000000..20165b1 --- /dev/null +++ b/test/Transforms/InstCombine/vector_gep2.ll @@ -0,0 +1,11 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define <2 x i8*> @testa(<2 x i8*> %a) { +; CHECK: @testa + %g = getelementptr <2 x i8*> %a, <2 x i32> <i32 0, i32 1> +; CHECK: getelementptr <2 x i8*> %a, <2 x i64> <i64 0, i64 1> + ret <2 x i8*> %g +} diff --git a/test/Transforms/InstCombine/weak-symbols.ll b/test/Transforms/InstCombine/weak-symbols.ll new file mode 100644 index 0000000..0039b59 --- /dev/null +++ b/test/Transforms/InstCombine/weak-symbols.ll @@ -0,0 +1,33 @@ +; PR4738 - Test that the library call simplifier doesn't assume anything about +; weak symbols. +; +; RUN: opt < %s -instcombine -S | FileCheck %s + +@real_init = weak_odr constant [2 x i8] c"y\00" +@fake_init = weak constant [2 x i8] c"y\00" +@.str = private constant [2 x i8] c"y\00" + +define i32 @foo() nounwind { +; CHECK: define i32 @foo +; CHECK: call i32 @strcmp +; CHECK: ret i32 %temp1 + +entry: + %str1 = getelementptr inbounds [2 x i8]* @fake_init, i64 0, i64 0 + %str2 = getelementptr inbounds [2 x i8]* @.str, i64 0, i64 0 + %temp1 = call i32 @strcmp(i8* %str1, i8* %str2) nounwind readonly + ret i32 %temp1 +} + +define i32 @bar() nounwind { +; CHECK: define i32 @bar +; CHECK: ret i32 0 + +entry: + %str1 = getelementptr inbounds [2 x i8]* @real_init, i64 0, i64 0 + %str2 = getelementptr inbounds [2 x i8]* @.str, i64 0, i64 0 + %temp1 = call i32 @strcmp(i8* %str1, i8* %str2) nounwind readonly + ret i32 %temp1 +} + +declare i32 @strcmp(i8*, i8*) nounwind readonly |