1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Test that the strncat libcall simplifier works correctly. 3; 4; RUN: opt < %s -passes=instcombine -S | FileCheck %s 5 6target 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" 7 8@hello = constant [6 x i8] c"hello\00" 9@empty = constant [1 x i8] c"\00" 10@a = common global [32 x i8] zeroinitializer, align 1 11declare ptr @strncat(ptr, ptr, i32) 12 13define void @test_simplify1() { 14; CHECK-LABEL: @test_simplify1( 15; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(ptr noundef nonnull dereferenceable(1) @a) 16; CHECK-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds i8, ptr @a, i32 [[STRLEN]] 17; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(6) [[ENDPTR]], ptr noundef nonnull align 1 dereferenceable(6) @hello, i32 6, i1 false) 18; CHECK-NEXT: ret void 19; 20 21 call ptr @strncat(ptr @a, ptr @hello, i32 13) 22 ret void 23} 24 25define void @test_simplify2() { 26; CHECK-LABEL: @test_simplify2( 27; CHECK-NEXT: ret void 28; 29 30 call ptr @strncat(ptr @a, ptr @empty, i32 13) 31 ret void 32} 33 34define void @test_simplify3() { 35; CHECK-LABEL: @test_simplify3( 36; CHECK-NEXT: ret void 37; 38 39 call ptr @strncat(ptr @a, ptr @hello, i32 0) 40 ret void 41} 42 43define void @test_nosimplify1() { 44; CHECK-LABEL: @test_nosimplify1( 45; CHECK-NEXT: [[TMP1:%.*]] = call ptr @strncat(ptr noundef nonnull dereferenceable(1) @a, ptr noundef nonnull dereferenceable(6) @hello, i32 1) 46; CHECK-NEXT: ret void 47; 48 49 call ptr @strncat(ptr @a, ptr @hello, i32 1) 50 ret void 51} 52 53; strncat(nonnull x, nonnull y, n) -> strncat(nonnull x, y, n) 54define ptr @test1(ptr %str1, ptr %str2, i32 %n) { 55; CHECK-LABEL: @test1( 56; CHECK-NEXT: [[TEMP1:%.*]] = call ptr @strncat(ptr noundef nonnull dereferenceable(1) [[STR1:%.*]], ptr nonnull [[STR2:%.*]], i32 [[N:%.*]]) 57; CHECK-NEXT: ret ptr [[TEMP1]] 58; 59 60 %temp1 = call ptr @strncat(ptr nonnull %str1, ptr nonnull %str2, i32 %n) 61 ret ptr %temp1 62} 63 64; strncat(x, y, 0) -> x 65define ptr @test2(ptr %str1, ptr %str2, i32 %n) { 66; CHECK-LABEL: @test2( 67; CHECK-NEXT: ret ptr [[STR1:%.*]] 68; 69 70 %temp1 = call ptr @strncat(ptr %str1, ptr %str2, i32 0) 71 ret ptr %temp1 72} 73 74; strncat(x, y, 5) -> strncat(nonnull x, nonnull y, 5) 75define ptr @test3(ptr %str1, ptr %str2, i32 %n) { 76; CHECK-LABEL: @test3( 77; CHECK-NEXT: [[TEMP1:%.*]] = call ptr @strncat(ptr noundef nonnull dereferenceable(1) [[STR1:%.*]], ptr noundef nonnull dereferenceable(1) [[STR2:%.*]], i32 5) 78; CHECK-NEXT: ret ptr [[TEMP1]] 79; 80 81 %temp1 = call ptr @strncat(ptr %str1, ptr %str2, i32 5) 82 ret ptr %temp1 83} 84 85define ptr @test4(ptr %str1, ptr %str2, i32 %n) null_pointer_is_valid { 86; CHECK-LABEL: @test4( 87; CHECK-NEXT: [[TEMP1:%.*]] = call ptr @strncat(ptr noundef [[STR1:%.*]], ptr [[STR2:%.*]], i32 [[N:%.*]]) 88; CHECK-NEXT: ret ptr [[TEMP1]] 89; 90 91 %temp1 = call ptr @strncat(ptr %str1, ptr %str2, i32 %n) 92 ret ptr %temp1 93} 94 95define ptr @test5(ptr %str, i32 %n) { 96; CHECK-LABEL: @test5( 97; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(ptr noundef nonnull dereferenceable(1) [[STR:%.*]]) 98; CHECK-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds i8, ptr [[STR]], i32 [[STRLEN]] 99; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(6) [[ENDPTR]], ptr noundef nonnull align 1 dereferenceable(6) @hello, i32 6, i1 false) 100; CHECK-NEXT: ret ptr [[STR]] 101; 102 %temp1 = call ptr @strncat(ptr %str, ptr @hello, i32 10) 103 ret ptr %temp1 104} 105