Files
clang-p2996/llvm/test/Transforms/InstCombine/strncat-2.ll
Nikita Popov 635f93dff7 [SimplifyLibCalls] Place deref attr even if nonnull already set
If nonnull is already set, we currently skip setting both nonnull
and dereferenceable. Make these independent, to avoid regressions
when additional nonnull attributes are inferred earlier.
2022-10-04 11:26:15 +02:00

105 lines
3.5 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; Test that the strncat libcall simplifier works correctly.
;
; RUN: opt < %s -passes=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 ptr @strncat(ptr, ptr, i32)
define void @test_simplify1() {
; CHECK-LABEL: @test_simplify1(
; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(ptr noundef nonnull dereferenceable(1) @a)
; CHECK-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds i8, ptr @a, i32 [[STRLEN]]
; 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)
; CHECK-NEXT: ret void
;
call ptr @strncat(ptr @a, ptr @hello, i32 13)
ret void
}
define void @test_simplify2() {
; CHECK-LABEL: @test_simplify2(
; CHECK-NEXT: ret void
;
call ptr @strncat(ptr @a, ptr @empty, i32 13)
ret void
}
define void @test_simplify3() {
; CHECK-LABEL: @test_simplify3(
; CHECK-NEXT: ret void
;
call ptr @strncat(ptr @a, ptr @hello, i32 0)
ret void
}
define void @test_nosimplify1() {
; CHECK-LABEL: @test_nosimplify1(
; CHECK-NEXT: [[TMP1:%.*]] = call ptr @strncat(ptr noundef nonnull dereferenceable(1) @a, ptr noundef nonnull dereferenceable(6) @hello, i32 1)
; CHECK-NEXT: ret void
;
call ptr @strncat(ptr @a, ptr @hello, i32 1)
ret void
}
; strncat(nonnull x, nonnull y, n) -> strncat(nonnull x, y, n)
define ptr @test1(ptr %str1, ptr %str2, i32 %n) {
; CHECK-LABEL: @test1(
; CHECK-NEXT: [[TEMP1:%.*]] = call ptr @strncat(ptr noundef nonnull dereferenceable(1) [[STR1:%.*]], ptr nonnull [[STR2:%.*]], i32 [[N:%.*]])
; CHECK-NEXT: ret ptr [[TEMP1]]
;
%temp1 = call ptr @strncat(ptr nonnull %str1, ptr nonnull %str2, i32 %n)
ret ptr %temp1
}
; strncat(x, y, 0) -> x
define ptr @test2(ptr %str1, ptr %str2, i32 %n) {
; CHECK-LABEL: @test2(
; CHECK-NEXT: ret ptr [[STR1:%.*]]
;
%temp1 = call ptr @strncat(ptr %str1, ptr %str2, i32 0)
ret ptr %temp1
}
; strncat(x, y, 5) -> strncat(nonnull x, nonnull y, 5)
define ptr @test3(ptr %str1, ptr %str2, i32 %n) {
; CHECK-LABEL: @test3(
; CHECK-NEXT: [[TEMP1:%.*]] = call ptr @strncat(ptr noundef nonnull dereferenceable(1) [[STR1:%.*]], ptr noundef nonnull dereferenceable(1) [[STR2:%.*]], i32 5)
; CHECK-NEXT: ret ptr [[TEMP1]]
;
%temp1 = call ptr @strncat(ptr %str1, ptr %str2, i32 5)
ret ptr %temp1
}
define ptr @test4(ptr %str1, ptr %str2, i32 %n) null_pointer_is_valid {
; CHECK-LABEL: @test4(
; CHECK-NEXT: [[TEMP1:%.*]] = call ptr @strncat(ptr noundef [[STR1:%.*]], ptr [[STR2:%.*]], i32 [[N:%.*]])
; CHECK-NEXT: ret ptr [[TEMP1]]
;
%temp1 = call ptr @strncat(ptr %str1, ptr %str2, i32 %n)
ret ptr %temp1
}
define ptr @test5(ptr %str, i32 %n) {
; CHECK-LABEL: @test5(
; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(ptr noundef nonnull dereferenceable(1) [[STR:%.*]])
; CHECK-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds i8, ptr [[STR]], i32 [[STRLEN]]
; 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)
; CHECK-NEXT: ret ptr [[STR]]
;
%temp1 = call ptr @strncat(ptr %str, ptr @hello, i32 10)
ret ptr %temp1
}