forked from OSchip/llvm-project
[InstCombine] Tighten up known library function signature tests (PR #56463)
Replace a switch statement used to validate arguments to known library functions with a more consistent table-driven approach and tighten it up.
This commit is contained in:
parent
276e108bf9
commit
0dcfe7aa35
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -5,7 +5,7 @@
|
|||
define amdgpu_ps void @main(<4 x float> inreg %reg0) {
|
||||
entry:
|
||||
%0 = extractelement <4 x float> %reg0, i32 0
|
||||
%1 = call float @fabs(float %0)
|
||||
%1 = call float @fabsf(float %0)
|
||||
%2 = fptoui float %1 to i32
|
||||
%3 = bitcast i32 %2 to float
|
||||
%4 = insertelement <4 x float> undef, float %3, i32 0
|
||||
|
@ -13,5 +13,5 @@ entry:
|
|||
ret void
|
||||
}
|
||||
|
||||
declare float @fabs(float ) readnone
|
||||
declare float @fabsf(float ) readnone
|
||||
declare void @llvm.r600.store.swizzle(<4 x float>, i32, i32)
|
||||
|
|
|
@ -4,38 +4,38 @@
|
|||
|
||||
|
||||
; DAGCombiner will transform:
|
||||
; (fabs (f32 bitcast (i32 a))) => (f32 bitcast (and (i32 a), 0x7FFFFFFF))
|
||||
; (fabsf (f32 bitcast (i32 a))) => (f32 bitcast (and (i32 a), 0x7FFFFFFF))
|
||||
; unless isFabsFree returns true
|
||||
|
||||
; FUNC-LABEL: {{^}}s_fabs_fn_free:
|
||||
; FUNC-LABEL: {{^}}s_fabsf_fn_free:
|
||||
; R600-NOT: AND
|
||||
; R600: |PV.{{[XYZW]}}|
|
||||
|
||||
; GCN: s_bitset0_b32 s{{[0-9]+}}, 31
|
||||
define amdgpu_kernel void @s_fabs_fn_free(float addrspace(1)* %out, i32 %in) {
|
||||
define amdgpu_kernel void @s_fabsf_fn_free(float addrspace(1)* %out, i32 %in) {
|
||||
%bc= bitcast i32 %in to float
|
||||
%fabs = call float @fabs(float %bc)
|
||||
%fabs = call float @fabsf(float %bc)
|
||||
store float %fabs, float addrspace(1)* %out
|
||||
ret void
|
||||
}
|
||||
|
||||
; FUNC-LABEL: {{^}}s_fabs_free:
|
||||
; FUNC-LABEL: {{^}}s_fabsf_free:
|
||||
; R600-NOT: AND
|
||||
; R600: |PV.{{[XYZW]}}|
|
||||
|
||||
; GCN: s_bitset0_b32 s{{[0-9]+}}, 31
|
||||
define amdgpu_kernel void @s_fabs_free(float addrspace(1)* %out, i32 %in) {
|
||||
define amdgpu_kernel void @s_fabsf_free(float addrspace(1)* %out, i32 %in) {
|
||||
%bc= bitcast i32 %in to float
|
||||
%fabs = call float @llvm.fabs.f32(float %bc)
|
||||
store float %fabs, float addrspace(1)* %out
|
||||
ret void
|
||||
}
|
||||
|
||||
; FUNC-LABEL: {{^}}s_fabs_f32:
|
||||
; FUNC-LABEL: {{^}}s_fabsf_f32:
|
||||
; R600: |{{(PV|T[0-9])\.[XYZW]}}|
|
||||
|
||||
; GCN: s_bitset0_b32 s{{[0-9]+}}, 31
|
||||
define amdgpu_kernel void @s_fabs_f32(float addrspace(1)* %out, float %in) {
|
||||
define amdgpu_kernel void @s_fabsf_f32(float addrspace(1)* %out, float %in) {
|
||||
%fabs = call float @llvm.fabs.f32(float %in)
|
||||
store float %fabs, float addrspace(1)* %out
|
||||
ret void
|
||||
|
@ -53,7 +53,7 @@ define amdgpu_kernel void @fabs_v2f32(<2 x float> addrspace(1)* %out, <2 x float
|
|||
ret void
|
||||
}
|
||||
|
||||
; FUNC-LABEL: {{^}}fabs_v4f32:
|
||||
; FUNC-LABEL: {{^}}fabsf_v4f32:
|
||||
; R600: |{{(PV|T[0-9])\.[XYZW]}}|
|
||||
; R600: |{{(PV|T[0-9])\.[XYZW]}}|
|
||||
; R600: |{{(PV|T[0-9])\.[XYZW]}}|
|
||||
|
@ -63,20 +63,20 @@ define amdgpu_kernel void @fabs_v2f32(<2 x float> addrspace(1)* %out, <2 x float
|
|||
; GCN: s_bitset0_b32
|
||||
; GCN: s_bitset0_b32
|
||||
; GCN: s_bitset0_b32
|
||||
define amdgpu_kernel void @fabs_v4f32(<4 x float> addrspace(1)* %out, <4 x float> %in) {
|
||||
define amdgpu_kernel void @fabsf_v4f32(<4 x float> addrspace(1)* %out, <4 x float> %in) {
|
||||
%fabs = call <4 x float> @llvm.fabs.v4f32(<4 x float> %in)
|
||||
store <4 x float> %fabs, <4 x float> addrspace(1)* %out
|
||||
ret void
|
||||
}
|
||||
|
||||
; GCN-LABEL: {{^}}fabs_fn_fold:
|
||||
; GCN-LABEL: {{^}}fabsf_fn_fold:
|
||||
; SI: s_load_dwordx4 s[[[#LOAD:]]:[[#END:]]], s[{{[0-9]+:[0-9]+}}], 0x9
|
||||
; VI: s_load_dwordx4 s[[[#LOAD:]]:[[#END:]]], s[{{[0-9]+:[0-9]+}}], 0x24
|
||||
; GCN-NOT: and
|
||||
; GCN: v_mov_b32_e32 [[V_MUL_VI:v[0-9]+]], s[[#LOAD + 3]]
|
||||
; GCN: v_mul_f32_e64 v{{[0-9]+}}, |s[[#LOAD + 2]]|, [[V_MUL_VI]]
|
||||
define amdgpu_kernel void @fabs_fn_fold(float addrspace(1)* %out, float %in0, float %in1) {
|
||||
%fabs = call float @fabs(float %in0)
|
||||
define amdgpu_kernel void @fabsf_fn_fold(float addrspace(1)* %out, float %in0, float %in1) {
|
||||
%fabs = call float @fabsf(float %in0)
|
||||
%fmul = fmul float %fabs, %in1
|
||||
store float %fmul, float addrspace(1)* %out
|
||||
ret void
|
||||
|
@ -95,10 +95,10 @@ define amdgpu_kernel void @fabs_fold(float addrspace(1)* %out, float %in0, float
|
|||
ret void
|
||||
}
|
||||
|
||||
; Make sure we turn some integer operations back into fabs
|
||||
; FUNC-LABEL: {{^}}bitpreserve_fabs_f32:
|
||||
; Make sure we turn some integer operations back into fabsf
|
||||
; FUNC-LABEL: {{^}}bitpreserve_fabsf_f32:
|
||||
; GCN: v_add_f32_e64 v{{[0-9]+}}, |s{{[0-9]+}}|, 1.0
|
||||
define amdgpu_kernel void @bitpreserve_fabs_f32(float addrspace(1)* %out, float %in) {
|
||||
define amdgpu_kernel void @bitpreserve_fabsf_f32(float addrspace(1)* %out, float %in) {
|
||||
%in.bc = bitcast float %in to i32
|
||||
%int.abs = and i32 %in.bc, 2147483647
|
||||
%bc = bitcast i32 %int.abs to float
|
||||
|
@ -107,7 +107,7 @@ define amdgpu_kernel void @bitpreserve_fabs_f32(float addrspace(1)* %out, float
|
|||
ret void
|
||||
}
|
||||
|
||||
declare float @fabs(float) readnone
|
||||
declare float @fabsf(float) readnone
|
||||
declare float @llvm.fabs.f32(float) readnone
|
||||
declare <2 x float> @llvm.fabs.v2f32(<2 x float>) readnone
|
||||
declare <4 x float> @llvm.fabs.v4f32(<4 x float>) readnone
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
; CHECK: FLOOR * T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
|
||||
define amdgpu_ps void @test(<4 x float> inreg %reg0) {
|
||||
%r0 = extractelement <4 x float> %reg0, i32 0
|
||||
%r1 = call float @floor(float %r0)
|
||||
%r1 = call float @floorf(float %r0)
|
||||
%vec = insertelement <4 x float> undef, float %r1, i32 0
|
||||
call void @llvm.r600.store.swizzle(<4 x float> %vec, i32 0, i32 0)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare float @floor(float) readonly
|
||||
declare float @floorf(float) readonly
|
||||
declare void @llvm.r600.store.swizzle(<4 x float>, i32, i32)
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
; RUN: llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck --check-prefixes=VI,FUNC %s
|
||||
; RUN: llc -amdgpu-scalarize-global-loads=false -march=r600 -mcpu=redwood < %s | FileCheck --check-prefixes=R600,FUNC %s
|
||||
|
||||
; FUNC-LABEL: {{^}}fneg_fabs_fadd_f32:
|
||||
; FUNC-LABEL: {{^}}fneg_fabsf_fadd_f32:
|
||||
; SI-NOT: and
|
||||
; SI: v_sub_f32_e64 {{v[0-9]+}}, {{s[0-9]+}}, |{{v[0-9]+}}|
|
||||
define amdgpu_kernel void @fneg_fabs_fadd_f32(float addrspace(1)* %out, float %x, float %y) {
|
||||
define amdgpu_kernel void @fneg_fabsf_fadd_f32(float addrspace(1)* %out, float %x, float %y) {
|
||||
%fabs = call float @llvm.fabs.f32(float %x)
|
||||
%fsub = fsub float -0.000000e+00, %fabs
|
||||
%fadd = fadd float %y, %fsub
|
||||
|
@ -13,11 +13,11 @@ define amdgpu_kernel void @fneg_fabs_fadd_f32(float addrspace(1)* %out, float %x
|
|||
ret void
|
||||
}
|
||||
|
||||
; FUNC-LABEL: {{^}}fneg_fabs_fmul_f32:
|
||||
; FUNC-LABEL: {{^}}fneg_fabsf_fmul_f32:
|
||||
; SI-NOT: and
|
||||
; SI: v_mul_f32_e64 {{v[0-9]+}}, {{s[0-9]+}}, -|{{v[0-9]+}}|
|
||||
; SI-NOT: and
|
||||
define amdgpu_kernel void @fneg_fabs_fmul_f32(float addrspace(1)* %out, float %x, float %y) {
|
||||
define amdgpu_kernel void @fneg_fabsf_fmul_f32(float addrspace(1)* %out, float %x, float %y) {
|
||||
%fabs = call float @llvm.fabs.f32(float %x)
|
||||
%fsub = fsub float -0.000000e+00, %fabs
|
||||
%fmul = fmul float %y, %fsub
|
||||
|
@ -26,17 +26,17 @@ define amdgpu_kernel void @fneg_fabs_fmul_f32(float addrspace(1)* %out, float %x
|
|||
}
|
||||
|
||||
; DAGCombiner will transform:
|
||||
; (fabs (f32 bitcast (i32 a))) => (f32 bitcast (and (i32 a), 0x7FFFFFFF))
|
||||
; (fabsf (f32 bitcast (i32 a))) => (f32 bitcast (and (i32 a), 0x7FFFFFFF))
|
||||
; unless isFabsFree returns true
|
||||
|
||||
; FUNC-LABEL: {{^}}fneg_fabs_free_f32:
|
||||
; FUNC-LABEL: {{^}}fneg_fabsf_free_f32:
|
||||
; R600-NOT: AND
|
||||
; R600: |PV.{{[XYZW]}}|
|
||||
; R600: -PV
|
||||
|
||||
; SI: s_or_b32 s{{[0-9]+}}, s{{[0-9]+}}, 0x80000000
|
||||
; VI: s_bitset1_b32 s{{[0-9]+}}, 31
|
||||
define amdgpu_kernel void @fneg_fabs_free_f32(float addrspace(1)* %out, i32 %in) {
|
||||
define amdgpu_kernel void @fneg_fabsf_free_f32(float addrspace(1)* %out, i32 %in) {
|
||||
%bc = bitcast i32 %in to float
|
||||
%fabs = call float @llvm.fabs.f32(float %bc)
|
||||
%fsub = fsub float -0.000000e+00, %fabs
|
||||
|
@ -44,32 +44,32 @@ define amdgpu_kernel void @fneg_fabs_free_f32(float addrspace(1)* %out, i32 %in)
|
|||
ret void
|
||||
}
|
||||
|
||||
; FUNC-LABEL: {{^}}fneg_fabs_fn_free_f32:
|
||||
; FUNC-LABEL: {{^}}fneg_fabsf_fn_free_f32:
|
||||
; R600-NOT: AND
|
||||
; R600: |PV.{{[XYZW]}}|
|
||||
; R600: -PV
|
||||
|
||||
; SI: s_or_b32 s{{[0-9]+}}, s{{[0-9]+}}, 0x80000000
|
||||
define amdgpu_kernel void @fneg_fabs_fn_free_f32(float addrspace(1)* %out, i32 %in) {
|
||||
define amdgpu_kernel void @fneg_fabsf_fn_free_f32(float addrspace(1)* %out, i32 %in) {
|
||||
%bc = bitcast i32 %in to float
|
||||
%fabs = call float @fabs(float %bc)
|
||||
%fabs = call float @fabsf(float %bc)
|
||||
%fsub = fsub float -0.000000e+00, %fabs
|
||||
store float %fsub, float addrspace(1)* %out
|
||||
ret void
|
||||
}
|
||||
|
||||
; FUNC-LABEL: {{^}}fneg_fabs_f32:
|
||||
; FUNC-LABEL: {{^}}fneg_fabsf_f32:
|
||||
; SI: s_or_b32 s{{[0-9]+}}, s{{[0-9]+}}, 0x80000000
|
||||
define amdgpu_kernel void @fneg_fabs_f32(float addrspace(1)* %out, float %in) {
|
||||
define amdgpu_kernel void @fneg_fabsf_f32(float addrspace(1)* %out, float %in) {
|
||||
%fabs = call float @llvm.fabs.f32(float %in)
|
||||
%fsub = fsub float -0.000000e+00, %fabs
|
||||
store float %fsub, float addrspace(1)* %out, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; FUNC-LABEL: {{^}}v_fneg_fabs_f32:
|
||||
; FUNC-LABEL: {{^}}v_fneg_fabsf_f32:
|
||||
; SI: v_or_b32_e32 v{{[0-9]+}}, 0x80000000, v{{[0-9]+}}
|
||||
define amdgpu_kernel void @v_fneg_fabs_f32(float addrspace(1)* %out, float addrspace(1)* %in) {
|
||||
define amdgpu_kernel void @v_fneg_fabsf_f32(float addrspace(1)* %out, float addrspace(1)* %in) {
|
||||
%val = load float, float addrspace(1)* %in, align 4
|
||||
%fabs = call float @llvm.fabs.f32(float %val)
|
||||
%fsub = fsub float -0.000000e+00, %fabs
|
||||
|
@ -77,7 +77,7 @@ define amdgpu_kernel void @v_fneg_fabs_f32(float addrspace(1)* %out, float addrs
|
|||
ret void
|
||||
}
|
||||
|
||||
; FUNC-LABEL: {{^}}fneg_fabs_v2f32:
|
||||
; FUNC-LABEL: {{^}}fneg_fabsf_v2f32:
|
||||
; R600: |{{(PV|T[0-9])\.[XYZW]}}|
|
||||
; R600: -PV
|
||||
; R600: |{{(PV|T[0-9])\.[XYZW]}}|
|
||||
|
@ -86,26 +86,26 @@ define amdgpu_kernel void @v_fneg_fabs_f32(float addrspace(1)* %out, float addrs
|
|||
; FIXME: In this case two uses of the constant should be folded
|
||||
; SI: s_bitset1_b32 s{{[0-9]+}}, 31
|
||||
; SI: s_bitset1_b32 s{{[0-9]+}}, 31
|
||||
define amdgpu_kernel void @fneg_fabs_v2f32(<2 x float> addrspace(1)* %out, <2 x float> %in) {
|
||||
define amdgpu_kernel void @fneg_fabsf_v2f32(<2 x float> addrspace(1)* %out, <2 x float> %in) {
|
||||
%fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %in)
|
||||
%fsub = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, %fabs
|
||||
store <2 x float> %fsub, <2 x float> addrspace(1)* %out
|
||||
ret void
|
||||
}
|
||||
|
||||
; FUNC-LABEL: {{^}}fneg_fabs_v4f32:
|
||||
; FUNC-LABEL: {{^}}fneg_fabsf_v4f32:
|
||||
; SI: s_bitset1_b32 s{{[0-9]+}}, 31
|
||||
; SI: s_bitset1_b32 s{{[0-9]+}}, 31
|
||||
; SI: s_bitset1_b32 s{{[0-9]+}}, 31
|
||||
; SI: s_bitset1_b32 s{{[0-9]+}}, 31
|
||||
define amdgpu_kernel void @fneg_fabs_v4f32(<4 x float> addrspace(1)* %out, <4 x float> %in) {
|
||||
define amdgpu_kernel void @fneg_fabsf_v4f32(<4 x float> addrspace(1)* %out, <4 x float> %in) {
|
||||
%fabs = call <4 x float> @llvm.fabs.v4f32(<4 x float> %in)
|
||||
%fsub = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %fabs
|
||||
store <4 x float> %fsub, <4 x float> addrspace(1)* %out
|
||||
ret void
|
||||
}
|
||||
|
||||
declare float @fabs(float) readnone
|
||||
declare float @fabsf(float) readnone
|
||||
declare float @llvm.fabs.f32(float) readnone
|
||||
declare <2 x float> @llvm.fabs.v2f32(<2 x float>) readnone
|
||||
declare <4 x float> @llvm.fabs.v4f32(<4 x float>) readnone
|
||||
|
|
|
@ -15,7 +15,7 @@ main_body:
|
|||
%tmp11 = extractelement <4 x float> %tmp9, i32 1
|
||||
%tmp12 = extractelement <4 x float> %tmp9, i32 2
|
||||
%tmp13 = extractelement <4 x float> %tmp9, i32 3
|
||||
%tmp14 = call float @fabs(float %tmp12)
|
||||
%tmp14 = call float @fabsf(float %tmp12)
|
||||
%tmp15 = fdiv float 1.000000e+00, %tmp14
|
||||
%tmp16 = fmul float %tmp10, %tmp15
|
||||
%tmp17 = fadd float %tmp16, 1.500000e+00
|
||||
|
@ -48,7 +48,7 @@ main_body:
|
|||
declare <4 x float> @llvm.r600.cube(<4 x float>) #0
|
||||
|
||||
; Function Attrs: readnone
|
||||
declare float @fabs(float) #0
|
||||
declare float @fabsf(float) #0
|
||||
|
||||
declare void @llvm.r600.store.swizzle(<4 x float>, i32, i32)
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ main_body:
|
|||
br i1 %10, label %IF, label %ELSE
|
||||
|
||||
IF: ; preds = %main_body
|
||||
%11 = call float @fabs(float %2)
|
||||
%11 = call float @fabsf(float %2)
|
||||
%12 = fcmp ueq float %11, 0x7FF0000000000000
|
||||
%13 = select i1 %12, float 1.000000e+00, float 0.000000e+00
|
||||
%14 = fsub float -0.000000e+00, %13
|
||||
|
@ -87,7 +87,7 @@ IF23: ; preds = %ELSE
|
|||
br label %ENDIF
|
||||
}
|
||||
|
||||
declare float @fabs(float) #0
|
||||
declare float @fabsf(float) #0
|
||||
|
||||
declare void @llvm.r600.store.swizzle(<4 x float>, i32, i32)
|
||||
|
||||
|
|
|
@ -266,7 +266,7 @@ define i32 addrspace(1)* @test13_addrspacecast() {
|
|||
|
||||
declare noalias i8* @malloc(i64) willreturn allockind("alloc,uninitialized")
|
||||
declare noalias i8* @custom_malloc(i32) willreturn
|
||||
declare noalias i8* @calloc(i32, i32) willreturn allockind("alloc,zeroed")
|
||||
declare noalias i8* @calloc(i64, i64) willreturn allockind("alloc,zeroed")
|
||||
|
||||
define void @test14(i32* %Q) {
|
||||
; CHECK-LABEL: @test14(
|
||||
|
@ -321,7 +321,7 @@ define void @test21() {
|
|||
; CHECK-LABEL: @test21(
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%m = call i8* @calloc(i32 9, i32 7)
|
||||
%m = call i8* @calloc(i64 9, i64 7)
|
||||
store i8 0, i8* %m
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
; Verify that incompatible declarations of known library functions are
|
||||
; not annotated with argument attributes. This negative test complements
|
||||
; annotate.ll.
|
||||
;
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -inferattrs -opaque-pointers -S | FileCheck %s --match-full-lines
|
||||
|
||||
|
||||
; Exercise <math.h> function declarations.
|
||||
|
||||
; Expect double fabs(double).
|
||||
declare float @fabs(float)
|
||||
; CHECK: declare float @fabs(float)
|
||||
|
||||
|
||||
; Exercise <stdio.h> function declarations.
|
||||
|
||||
; Expect int fgetc(FILE*).
|
||||
declare i32 @fgetc(ptr, i32)
|
||||
; CHECK: declare i32 @fgetc(ptr, i32)
|
||||
|
||||
; Expect char* fgets(char*, int, FILE*).
|
||||
declare i32 @fgets(ptr, i32, ptr)
|
||||
; CHECK: declare i32 @fgets(ptr, i32, ptr)
|
||||
|
||||
; Expect int sprintf(char*, const char*, ...).
|
||||
declare i32 @sprintf(ptr, i64, ptr, ...)
|
||||
; CHECK: declare i32 @sprintf(ptr, i64, ptr, ...)
|
||||
|
||||
; Expect int snprintf(char*, size_t, const char*, ...).
|
||||
declare i32 @snprintf(ptr, i64, ptr)
|
||||
; CHECK: declare i32 @snprintf(ptr, i64, ptr)
|
||||
|
||||
; Expect int sscanf(const char*, const char*, ...).
|
||||
declare i32 @sscanf(ptr, ...)
|
||||
; CHECK: declare i32 @sscanf(ptr, ...)
|
||||
|
||||
|
||||
; Exercise <stdlib.h> function declarations.
|
||||
|
||||
; Expect int atoi(const char*).
|
||||
declare i8 @atoi(ptr)
|
||||
; CHECK: declare i8 @atoi(ptr)
|
||||
|
||||
; Expect long long atoll(const char*).
|
||||
declare i1 @atoll(ptr)
|
||||
; CHECK: declare i1 @atoll(ptr)
|
||||
|
||||
; Expect double atof(const char*).
|
||||
declare float @atof(ptr)
|
||||
; CHECK: declare float @atof(ptr)
|
||||
|
||||
; Expect double strtod(const char*, char**).
|
||||
declare double @strtod(ptr, ptr, i32)
|
||||
; CHECK: declare double @strtod(ptr, ptr, i32)
|
||||
|
||||
; Expect float strtof(const char*, char**).
|
||||
declare double @strtof(ptr, ptr)
|
||||
; CHECK: declare double @strtof(ptr, ptr)
|
||||
|
||||
|
||||
; Exercise <string.h> function declarations.
|
||||
|
||||
; Expect void* memccpy(void*, const void*, int, size_t).
|
||||
declare ptr @memccpy(ptr, ptr, i64, i64)
|
||||
; CHECK: declare ptr @memccpy(ptr, ptr, i64, i64)
|
||||
|
||||
; Expect int strcasecmp(const char*, const char*).
|
||||
declare i1 @strcasecmp(ptr, ptr)
|
||||
; CHECK: declare i1 @strcasecmp(ptr, ptr)
|
||||
|
||||
; Expect int strcoll(const char*, const char*).
|
||||
declare ptr @strcoll(ptr, ptr)
|
||||
; CHECK: declare ptr @strcoll(ptr, ptr)
|
||||
|
||||
; Expect int strncasecmp(const char*, const char*, size_t).
|
||||
declare i32 @strncasecmp(ptr, ptr, i64, i64)
|
||||
; CHECK: declare i32 @strncasecmp(ptr, ptr, i64, i64)
|
||||
|
||||
; Expect int strxfrm(const char*, const char*).
|
||||
declare i16 @strxfrm(ptr, ptr)
|
||||
; CHECK: declare i16 @strxfrm(ptr, ptr)
|
||||
|
||||
; Expect char* strtok(const char*, const char*).
|
||||
declare ptr @strtok(ptr, i8)
|
||||
; CHECK: declare ptr @strtok(ptr, i8)
|
||||
|
||||
; Expect char* strtok_r(const char*, const char*, char**).
|
||||
declare ptr @strtok_r(ptr, ptr, i64)
|
||||
; CHECK: declare ptr @strtok_r(ptr, ptr, i64)
|
||||
|
||||
; Expect char* strdup(const char*).
|
||||
declare ptr @strdup(ptr, i64)
|
||||
; CHECK: declare ptr @strdup(ptr, i64)
|
||||
|
||||
; Expect char* strndup(const char*, size_t).
|
||||
declare ptr @strndup(ptr, i64, i64)
|
||||
; CHECK: declare ptr @strndup(ptr, i64, i64)
|
||||
|
||||
|
||||
; Exercise <sys/stat.h> and <sys/statvfs.h> function declarations.
|
||||
|
||||
; Expect int stat(const char*, struct stat*).
|
||||
declare i32 @stat(ptr, ptr, i64)
|
||||
; CHECK: declare i32 @stat(ptr, ptr, i64)
|
||||
|
||||
; Expect int statvfs(const char*, struct statvfs*).
|
||||
declare i32 @statvfs(ptr, ptr, i64)
|
||||
; CHECK: declare i32 @statvfs(ptr, ptr, i64)
|
|
@ -314,6 +314,11 @@ declare float @ceilf(float)
|
|||
; CHECK: declare x86_fp80 @ceill(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
|
||||
declare x86_fp80 @ceill(x86_fp80)
|
||||
|
||||
; The second argument of int chmod(FILE*, mode_t) is a 32-bit int on most
|
||||
; targets but it's a 16-bit short on Apple Darwin. Use i16 here to verify
|
||||
; the function is still recognized.
|
||||
; FIXME: this should be tightened up to verify that only the type with
|
||||
; the right size for the target matches.
|
||||
; CHECK: declare noundef i32 @chmod(i8* nocapture noundef readonly, i16 noundef zeroext) [[NOFREE_NOUNWIND]]
|
||||
declare i32 @chmod(i8*, i16 zeroext)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
|
||||
; RUN: opt < %s -passes=instcombine -data-layout=p:32:32 -S | FileCheck %s
|
||||
|
||||
declare void @bcopy(i8* nocapture readonly, i8* nocapture, i32)
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ declare noalias i8* @strdup(i8*)
|
|||
declare noalias i8* @aligned_alloc(i64 allocalign, i64) allockind("alloc,uninitialized,aligned") allocsize(1) "alloc-family"="malloc"
|
||||
declare noalias align 16 i8* @memalign(i64, i64)
|
||||
; new[](unsigned int, align_val_t)
|
||||
declare noalias i8* @_ZnajSt11align_val_t(i64 %size, i64 %align)
|
||||
declare noalias i8* @_ZnamSt11align_val_t(i64 %size, i64 %align)
|
||||
|
||||
declare i8* @my_malloc(i64) allocsize(0)
|
||||
declare i8* @my_calloc(i64, i64) allocsize(0, 1)
|
||||
|
||||
|
@ -349,10 +350,10 @@ bb:
|
|||
|
||||
define noalias i8* @op_new_align() {
|
||||
; CHECK-LABEL: @op_new_align(
|
||||
; CHECK-NEXT: [[CALL:%.*]] = tail call align 32 dereferenceable_or_null(32) i8* @_ZnajSt11align_val_t(i64 32, i64 32)
|
||||
; CHECK-NEXT: [[CALL:%.*]] = tail call align 32 dereferenceable_or_null(32) i8* @_ZnamSt11align_val_t(i64 32, i64 32)
|
||||
; CHECK-NEXT: ret i8* [[CALL]]
|
||||
;
|
||||
%call = tail call i8* @_ZnajSt11align_val_t(i64 32, i64 32)
|
||||
%call = tail call i8* @_ZnamSt11align_val_t(i64 32, i64 32)
|
||||
ret i8* %call
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
|
|||
@percent_d = constant [3 x i8] c"%d\00"
|
||||
@percent_f = constant [3 x i8] c"%f\00"
|
||||
@percent_s = constant [3 x i8] c"%s\00"
|
||||
@percent_m = constant [3 x i8] c"%m\00"
|
||||
|
||||
declare i32 @fprintf(%FILE*, i8*, ...)
|
||||
|
||||
|
@ -96,3 +97,15 @@ define i32 @test_no_simplify3(%FILE* %fp) {
|
|||
ret i32 %1
|
||||
; CHECK-NEXT: ret i32 %1
|
||||
}
|
||||
|
||||
; Verify that a call with a format string containing just the %m directive
|
||||
; and no arguments is not simplified.
|
||||
|
||||
define void @test_no_simplify4(%FILE* %fp) {
|
||||
; CHECK-LABEL: @test_no_simplify4(
|
||||
%fmt = getelementptr [3 x i8], [3 x i8]* @percent_m, i32 0, i32 0
|
||||
call i32 (%FILE*, i8*, ...) @fprintf(%FILE* %fp, i8* %fmt)
|
||||
; CHECK-NEXT: call i32 (%FILE*, i8*, ...) @fprintf(%FILE* %fp, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_m, i32 0, i32 0))
|
||||
ret void
|
||||
; CHECK-NEXT: ret void
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
;
|
||||
; 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"
|
||||
target datalayout = "e-p:64:64:64"
|
||||
|
||||
%FILE = type { }
|
||||
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -passes=instcombine -S < %s | FileCheck %s
|
||||
|
||||
declare i32 @memcmp(i8 addrspace(1)* nocapture, i8* nocapture, i64)
|
||||
declare i32 @memcmp(i8 addrspace(1)* nocapture, i8 addrspace(1)* nocapture, i64)
|
||||
|
||||
define i32 @memcmp_const_size_update_deref(i8 addrspace(1)* nocapture readonly %d, i8* nocapture readonly %s) {
|
||||
define i32 @memcmp_const_size_update_deref(i8 addrspace(1)* nocapture readonly %d, i8 addrspace(1)* nocapture readonly %s) {
|
||||
; CHECK-LABEL: @memcmp_const_size_update_deref(
|
||||
; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8 addrspace(1)* noundef dereferenceable(16) dereferenceable_or_null(40) [[D:%.*]], i8* noundef nonnull dereferenceable(16) [[S:%.*]], i64 16)
|
||||
; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8 addrspace(1)* noundef dereferenceable(16) dereferenceable_or_null(40) [[D:%.*]], i8 addrspace(1)* noundef dereferenceable(16) [[S:%.*]], i64 16)
|
||||
; CHECK-NEXT: ret i32 [[CALL]]
|
||||
;
|
||||
%call = tail call i32 @memcmp(i8 addrspace(1)* dereferenceable_or_null(40) %d, i8* %s, i64 16)
|
||||
%call = tail call i32 @memcmp(i8 addrspace(1)* dereferenceable_or_null(40) %d, i8 addrspace(1)* %s, i64 16)
|
||||
ret i32 %call
|
||||
}
|
||||
|
||||
define i32 @memcmp_nonconst_size_nonnnull(i8 addrspace(1)* nocapture readonly %d, i8* nocapture readonly %s, i64 %n) {
|
||||
define i32 @memcmp_nonconst_size_nonnnull(i8 addrspace(1)* nocapture readonly %d, i8 addrspace(1)* nocapture readonly %s, i64 %n) {
|
||||
; CHECK-LABEL: @memcmp_nonconst_size_nonnnull(
|
||||
; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8 addrspace(1)* nonnull dereferenceable_or_null(40) [[D:%.*]], i8* nonnull [[S:%.*]], i64 [[N:%.*]])
|
||||
; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8 addrspace(1)* nonnull dereferenceable_or_null(40) [[D:%.*]], i8 addrspace(1)* nonnull [[S:%.*]], i64 [[N:%.*]])
|
||||
; CHECK-NEXT: ret i32 [[CALL]]
|
||||
;
|
||||
%call = tail call i32 @memcmp(i8 addrspace(1)* nonnull dereferenceable_or_null(40) %d, i8* nonnull %s, i64 %n)
|
||||
%call = tail call i32 @memcmp(i8 addrspace(1)* nonnull dereferenceable_or_null(40) %d, i8 addrspace(1)* nonnull %s, i64 %n)
|
||||
ret i32 %call
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
declare i32 @memcmp(i8* nocapture, i8* nocapture, i64)
|
||||
declare i8* @memcpy(i8* nocapture, i8* nocapture, i64)
|
||||
declare i8* @memmove(i8* nocapture, i8* nocapture, i64)
|
||||
declare i8* @memset(i8* nocapture, i8, i64)
|
||||
declare i8* @memset(i8* nocapture, i32, i64)
|
||||
declare i8* @memchr(i8* nocapture, i32, i64)
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1)
|
||||
declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1)
|
||||
|
@ -118,12 +118,13 @@ define i8* @memmove_const_size_set_deref(i8* nocapture readonly %d, i8* nocaptur
|
|||
ret i8* %call
|
||||
}
|
||||
|
||||
define i8* @memset_const_size_set_deref(i8* nocapture readonly %s, i8 %c) {
|
||||
define i8* @memset_const_size_set_deref(i8* nocapture readonly %s, i32 %c) {
|
||||
; CHECK-LABEL: @memset_const_size_set_deref(
|
||||
; CHECK-NEXT: tail call void @llvm.memset.p0i8.i64(i8* noundef nonnull align 1 dereferenceable(64) [[S:%.*]], i8 [[C:%.*]], i64 64, i1 false)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8
|
||||
; CHECK-NEXT: tail call void @llvm.memset.p0i8.i64(i8* noundef nonnull align 1 dereferenceable(64) [[S:%.*]], i8 [[TMP1]], i64 64, i1 false)
|
||||
; CHECK-NEXT: ret i8* [[S]]
|
||||
;
|
||||
%call = tail call i8* @memset(i8* %s, i8 %c, i64 64)
|
||||
%call = tail call i8* @memset(i8* %s, i32 %c, i64 64)
|
||||
ret i8* %call
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
|
||||
|
||||
; Set pointer (and size_t) size to 32 bits. This lets the declarations
|
||||
; below and calls to them be recognized as special.
|
||||
|
||||
target datalayout = "p:32:32"
|
||||
|
||||
%size_t = type i32
|
||||
%align_val_t = type %size_t
|
||||
%nothrow_t = type { }
|
||||
|
||||
|
||||
; operator new(size_t = unsigned int)
|
||||
declare i8* @_Znwj(%size_t)
|
||||
|
||||
; operator new[](size_t = unsigned int)
|
||||
declare i8* @_Znaj(%size_t)
|
||||
|
||||
; operator new(size_t = unsigned int, std::align_val_t)
|
||||
declare i8* @_ZnwjSt11align_val_t(%size_t, %size_t)
|
||||
|
||||
; operator new[](size_t = unsigned int, std::align_val_t)
|
||||
declare i8* @_ZnajSt11align_val_t(%size_t, %size_t)
|
||||
|
||||
; operator new(size_t = unsigned int, std::align_val_t, const std::nothrow_t&)
|
||||
declare i8* @_ZnwjSt11align_val_tRKSt9nothrow_t(%size_t, %size_t, %nothrow_t*)
|
||||
|
||||
; operator new[](size_t = unsigned int, std::align_val_t, const std::nothrow_t&)
|
||||
declare i8* @_ZnajSt11align_val_tRKSt9nothrow_t(%size_t, %size_t, %nothrow_t*)
|
||||
|
||||
|
||||
; operator delete(void*, size_t = unsigned int)
|
||||
declare void @_ZdlPvj(i8*, %size_t)
|
||||
|
||||
; operator delete[](void*, size_t = unsigned int)
|
||||
declare void @_ZdaPvj(i8*, %size_t)
|
||||
|
||||
; operator delete(void*, std::align_val_t)
|
||||
declare void @_ZdlPvSt11align_val_t(i8*, %align_val_t)
|
||||
|
||||
; operator delete[](void*, std::align_val_t)
|
||||
declare void @_ZdaPvSt11align_val_t(i8*, %align_val_t)
|
||||
|
||||
; operator delete(void*, size_t = unsigned int, std::align_val_t)
|
||||
declare void @_ZdlPvjSt11align_val_t(i8*, %size_t, %align_val_t)
|
||||
|
||||
; operator delete[](void*, size_t = unsigned int, std::align_val_t)
|
||||
declare void @_ZdaPvjSt11align_val_t(i8*, %size_t, %align_val_t)
|
||||
|
||||
; operator delete(void*, std::align_val_t, const std::nothrow_t&)
|
||||
declare void @_ZdlPvSt11align_val_tRKSt9nothrow_t(i8*, %align_val_t, %nothrow_t*)
|
||||
|
||||
; operator delete[](void*, std::align_val_t, const std::nothrow_t&)
|
||||
declare void @_ZdaPvSt11align_val_tRKSt9nothrow_t(i8*, %align_val_t, %nothrow_t*)
|
||||
|
||||
declare void @llvm.assume(i1)
|
||||
|
||||
|
||||
; Verify that pairs of matching calls to new/delete are eliminated.
|
||||
|
||||
define void @elim_new_delete_pairs() {
|
||||
; CHECK-LABEL: @elim_new_delete_pairs(
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%nt = alloca %nothrow_t
|
||||
|
||||
%nwj = call i8* @_Znwj(%size_t 32)
|
||||
call void @_ZdlPvj(i8* %nwj, %size_t 32)
|
||||
|
||||
%naj = call i8* @_Znaj(%size_t 32)
|
||||
call void @_ZdaPvj(i8* %naj, %size_t 32)
|
||||
|
||||
%nwja = call i8* @_ZnwjSt11align_val_t(%size_t 32, %size_t 8)
|
||||
call void @_ZdlPvSt11align_val_t(i8* %nwja, %size_t 8)
|
||||
|
||||
%naja = call i8* @_ZnajSt11align_val_t(%size_t 32, %size_t 8)
|
||||
call void @_ZdaPvSt11align_val_t(i8* %naja, i32 8)
|
||||
|
||||
%nwjat = call i8* @_ZnwjSt11align_val_tRKSt9nothrow_t(%size_t 32, %size_t 8, %nothrow_t* %nt)
|
||||
call void @_ZdlPvSt11align_val_tRKSt9nothrow_t(i8* %nwjat, %size_t 8, %nothrow_t* %nt)
|
||||
|
||||
%najat = call i8* @_ZnajSt11align_val_tRKSt9nothrow_t(%size_t 32, %size_t 8, %nothrow_t* %nt)
|
||||
call void @_ZdaPvSt11align_val_tRKSt9nothrow_t(i8* %najat, i32 8, %nothrow_t* %nt)
|
||||
|
||||
%nwja2 = call i8* @_ZnwjSt11align_val_t(%size_t 32, %size_t 8)
|
||||
call void @_ZdlPvjSt11align_val_t(i8* %nwja2, %size_t 32, %size_t 8)
|
||||
|
||||
%naja2 = call i8* @_ZnajSt11align_val_t(%size_t 32, %size_t 8)
|
||||
call void @_ZdaPvjSt11align_val_t(i8* %naja2, %size_t 32, %size_t 8)
|
||||
|
||||
; Check that the alignment assume does not prevent the removal.
|
||||
%nwa3 = call i8* @_ZnajSt11align_val_t(%size_t 32, %size_t 16)
|
||||
|
||||
call void @llvm.assume(i1 true) [ "align"(i8* %nwa3, i32 16) ]
|
||||
|
||||
call void @_ZdaPvjSt11align_val_t(i8* %nwa3, %size_t 32, %size_t 16)
|
||||
|
||||
ret void
|
||||
}
|
|
@ -111,16 +111,12 @@ define linkonce void @_ZdaPvj(i8* %p, i32) nobuiltin {
|
|||
|
||||
; new(size_t, align_val_t)
|
||||
declare i8* @_ZnwmSt11align_val_t(i64, i64) nobuiltin
|
||||
declare i8* @_ZnwjSt11align_val_t(i32, i32) nobuiltin
|
||||
; new[](size_t, align_val_t)
|
||||
declare i8* @_ZnamSt11align_val_t(i64, i64) nobuiltin
|
||||
declare i8* @_ZnajSt11align_val_t(i32, i32) nobuiltin
|
||||
; new(size_t, align_val_t, nothrow)
|
||||
declare i8* @_ZnwmSt11align_val_tRKSt9nothrow_t(i64, i64, i8*) nobuiltin
|
||||
declare i8* @_ZnwjSt11align_val_tRKSt9nothrow_t(i32, i32, i8*) nobuiltin
|
||||
; new[](size_t, align_val_t, nothrow)
|
||||
declare i8* @_ZnamSt11align_val_tRKSt9nothrow_t(i64, i64, i8*) nobuiltin
|
||||
declare i8* @_ZnajSt11align_val_tRKSt9nothrow_t(i32, i32, i8*) nobuiltin
|
||||
; delete(void*, align_val_t)
|
||||
declare void @_ZdlPvSt11align_val_t(i8*, i64) nobuiltin
|
||||
; delete[](void*, align_val_t)
|
||||
|
@ -129,12 +125,8 @@ declare void @_ZdaPvSt11align_val_t(i8*, i64) nobuiltin
|
|||
declare void @_ZdlPvSt11align_val_tRKSt9nothrow_t(i8*, i64, i8*) nobuiltin
|
||||
; delete[](void*, align_val_t, nothrow)
|
||||
declare void @_ZdaPvSt11align_val_tRKSt9nothrow_t(i8*, i64, i8*) nobuiltin
|
||||
; delete(void*, unsigned int, align_val_t)
|
||||
declare void @_ZdlPvjSt11align_val_t(i8*, i32, i32) nobuiltin
|
||||
; delete(void*, unsigned long, align_val_t)
|
||||
declare void @_ZdlPvmSt11align_val_t(i8*, i64, i64) nobuiltin
|
||||
; delete[](void*, unsigned int, align_val_t)
|
||||
declare void @_ZdaPvjSt11align_val_t(i8*, i32, i32) nobuiltin
|
||||
; delete[](void*, unsigned long, align_val_t)
|
||||
declare void @_ZdaPvmSt11align_val_t(i8*, i64, i64) nobuiltin
|
||||
|
||||
|
@ -151,36 +143,20 @@ define void @test8() {
|
|||
call void @_ZdaPv(i8* %na) builtin
|
||||
%nwm = call i8* @_Znwm(i64 32) builtin
|
||||
call void @_ZdlPvm(i8* %nwm, i64 32) builtin
|
||||
%nwj = call i8* @_Znwj(i32 32) builtin
|
||||
call void @_ZdlPvj(i8* %nwj, i32 32) builtin
|
||||
%nam = call i8* @_Znam(i64 32) builtin
|
||||
call void @_ZdaPvm(i8* %nam, i64 32) builtin
|
||||
%naj = call i8* @_Znaj(i32 32) builtin
|
||||
call void @_ZdaPvj(i8* %naj, i32 32) builtin
|
||||
%nwa = call i8* @_ZnwmSt11align_val_t(i64 32, i64 8) builtin
|
||||
call void @_ZdlPvSt11align_val_t(i8* %nwa, i64 8) builtin
|
||||
%naa = call i8* @_ZnamSt11align_val_t(i64 32, i64 8) builtin
|
||||
call void @_ZdaPvSt11align_val_t(i8* %naa, i64 8) builtin
|
||||
%nwja = call i8* @_ZnwjSt11align_val_t(i32 32, i32 8) builtin
|
||||
call void @_ZdlPvSt11align_val_t(i8* %nwja, i64 8) builtin
|
||||
%naja = call i8* @_ZnajSt11align_val_t(i32 32, i32 8) builtin
|
||||
call void @_ZdaPvSt11align_val_t(i8* %naja, i64 8) builtin
|
||||
%nwat = call i8* @_ZnwmSt11align_val_tRKSt9nothrow_t(i64 32, i64 8, i8* %nt) builtin
|
||||
call void @_ZdlPvSt11align_val_tRKSt9nothrow_t(i8* %nwat, i64 8, i8* %nt) builtin
|
||||
%naat = call i8* @_ZnamSt11align_val_tRKSt9nothrow_t(i64 32, i64 8, i8* %nt) builtin
|
||||
call void @_ZdaPvSt11align_val_tRKSt9nothrow_t(i8* %naat, i64 8, i8* %nt) builtin
|
||||
%nwjat = call i8* @_ZnwjSt11align_val_tRKSt9nothrow_t(i32 32, i32 8, i8* %nt) builtin
|
||||
call void @_ZdlPvSt11align_val_tRKSt9nothrow_t(i8* %nwjat, i64 8, i8* %nt) builtin
|
||||
%najat = call i8* @_ZnajSt11align_val_tRKSt9nothrow_t(i32 32, i32 8, i8* %nt) builtin
|
||||
call void @_ZdaPvSt11align_val_tRKSt9nothrow_t(i8* %najat, i64 8, i8* %nt) builtin
|
||||
%nwa2 = call i8* @_ZnwmSt11align_val_t(i64 32, i64 8) builtin
|
||||
call void @_ZdlPvmSt11align_val_t(i8* %nwa2, i64 32, i64 8) builtin
|
||||
%nwja2 = call i8* @_ZnwjSt11align_val_t(i32 32, i32 8) builtin
|
||||
call void @_ZdlPvjSt11align_val_t(i8* %nwa2, i32 32, i32 8) builtin
|
||||
%naa2 = call i8* @_ZnamSt11align_val_t(i64 32, i64 8) builtin
|
||||
call void @_ZdaPvmSt11align_val_t(i8* %naa2, i64 32, i64 8) builtin
|
||||
%naja2 = call i8* @_ZnajSt11align_val_t(i32 32, i32 8) builtin
|
||||
call void @_ZdaPvjSt11align_val_t(i8* %naja2, i32 32, i32 8) builtin
|
||||
|
||||
; Check that the alignment assume does not prevent the removal.
|
||||
%nwa3 = call i8* @_ZnwmSt11align_val_t(i64 32, i64 16) builtin
|
||||
|
|
|
@ -12,7 +12,7 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
|
|||
@charstr = constant [2 x i8] c"a\00"
|
||||
@empty = constant [1 x i8] c"\00"
|
||||
|
||||
declare void @printf(i8*, ...)
|
||||
declare i32 @printf(i8*, ...)
|
||||
|
||||
; Check simplification of printf with void return type.
|
||||
|
||||
|
@ -33,7 +33,7 @@ define void @test_simplify1() {
|
|||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%fmt = getelementptr [2 x i8], [2 x i8]* @h, i32 0, i32 0
|
||||
call void (i8*, ...) @printf(i8* %fmt)
|
||||
call i32 (i8*, ...) @printf(i8* %fmt)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ define void @test_simplify2() {
|
|||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%fmt = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0
|
||||
call void (i8*, ...) @printf(i8* %fmt)
|
||||
call i32 (i8*, ...) @printf(i8* %fmt)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ define void @test_simplify6() {
|
|||
;
|
||||
%fmt = getelementptr [4 x i8], [4 x i8]* @percent_s, i32 0, i32 0
|
||||
%str = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0
|
||||
call void (i8*, ...) @printf(i8* %fmt, i8* %str)
|
||||
call i32 (i8*, ...) @printf(i8* %fmt, i8* %str)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ define void @test_simplify7() {
|
|||
;
|
||||
%fmt = getelementptr [3 x i8], [3 x i8]* @format_str, i32 0, i32 0
|
||||
%str = getelementptr [2 x i8], [2 x i8]* @charstr, i32 0, i32 0
|
||||
call void (i8*, ...) @printf(i8* %fmt, i8* %str)
|
||||
call i32 (i8*, ...) @printf(i8* %fmt, i8* %str)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ define void @test_simplify8() {
|
|||
;
|
||||
%fmt = getelementptr [3 x i8], [3 x i8]* @format_str, i32 0, i32 0
|
||||
%str = getelementptr [1 x i8], [1 x i8]* @empty, i32 0, i32 0
|
||||
call void (i8*, ...) @printf(i8* %fmt, i8* %str)
|
||||
call i32 (i8*, ...) @printf(i8* %fmt, i8* %str)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ define void @test_simplify9() {
|
|||
;
|
||||
%fmt = getelementptr [3 x i8], [3 x i8]* @format_str, i32 0, i32 0
|
||||
%str = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0
|
||||
call void (i8*, ...) @printf(i8* %fmt, i8* %str)
|
||||
call i32 (i8*, ...) @printf(i8* %fmt, i8* %str)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -106,11 +106,11 @@ define void @test_simplify10() {
|
|||
;
|
||||
%fmt = getelementptr [3 x i8], [3 x i8]* @format_str, i32 0, i32 0
|
||||
%str1 = getelementptr [1 x i8], [1 x i8]* @empty, i32 0, i32 0
|
||||
call void (i8*, ...) @printf(i8* %fmt, i8* %str1, i32 42, double 0x40091EB860000000)
|
||||
call i32 (i8*, ...) @printf(i8* %fmt, i8* %str1, i32 42, double 0x40091EB860000000)
|
||||
%str2 = getelementptr [2 x i8], [2 x i8]* @charstr, i32 0, i32 0
|
||||
call void (i8*, ...) @printf(i8* %fmt, i8* %str2, i32 42, double 0x40091EB860000000)
|
||||
call i32 (i8*, ...) @printf(i8* %fmt, i8* %str2, i32 42, double 0x40091EB860000000)
|
||||
%str3 = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0
|
||||
call void (i8*, ...) @printf(i8* %fmt, i8* %str3, i32 42, double 0x40091EB860000000)
|
||||
call i32 (i8*, ...) @printf(i8* %fmt, i8* %str3, i32 42, double 0x40091EB860000000)
|
||||
ret void
|
||||
}
|
||||
;.
|
||||
|
|
|
@ -0,0 +1,340 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -S < %s -mtriple=unknown -passes=instcombine -instcombine-infinite-loop-threshold=2 | FileCheck -check-prefixes=CHECK,CHECK32 %s
|
||||
; RUN: opt -S < %s -mtriple=msp430 -passes=instcombine -instcombine-infinite-loop-threshold=2 | FileCheck -check-prefixes=CHECK,CHECK16 %s
|
||||
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32"
|
||||
|
||||
@G = constant [3 x i8] c"%s\00" ; <[3 x i8]*> [#uses=1]
|
||||
|
||||
; A 16-bit compatible sprintf is not recognized as the standard library
|
||||
; function on 32-bit targets.
|
||||
declare i16 @sprintf(i8*, i8*, ...)
|
||||
|
||||
define void @foo(i8* %P, i32* %X) {
|
||||
; CHECK32-LABEL: @foo(
|
||||
; CHECK32-NEXT: [[TMP1:%.*]] = call i16 (i8*, i8*, ...) @sprintf(i8* [[P:%.*]], i8* getelementptr inbounds ([3 x i8], [3 x i8]* @G, i32 0, i32 0), i32* [[X:%.*]])
|
||||
; CHECK32-NEXT: ret void
|
||||
;
|
||||
; CHECK16-LABEL: @foo(
|
||||
; CHECK16-NEXT: [[CSTR:%.*]] = bitcast i32* [[X:%.*]] to i8*
|
||||
; CHECK16-NEXT: [[STRCPY:%.*]] = call i8* @strcpy(i8* noundef nonnull dereferenceable(1) [[P:%.*]], i8* noundef nonnull dereferenceable(1) [[CSTR]])
|
||||
; CHECK16-NEXT: ret void
|
||||
;
|
||||
call i16 (i8*, i8*, ...) @sprintf(i8* %P, i8* getelementptr ([3 x i8], [3 x i8]* @G, i32 0, i32 0), i32* %X ) ; <i32>:1 [#uses=0]
|
||||
ret void
|
||||
}
|
||||
|
||||
; PR1307
|
||||
@str = internal constant [5 x i8] c"foog\00"
|
||||
@str1 = internal constant [8 x i8] c"blahhh!\00"
|
||||
@str2 = internal constant [5 x i8] c"Ponk\00"
|
||||
|
||||
define i8* @test1() {
|
||||
; CHECK32-LABEL: @test1(
|
||||
; CHECK32-NEXT: [[TMP3:%.*]] = tail call i8* @strchr(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @str, i32 0, i32 2), i16 103)
|
||||
; CHECK32-NEXT: ret i8* [[TMP3]]
|
||||
;
|
||||
; CHECK16-LABEL: @test1(
|
||||
; CHECK16-NEXT: ret i8* getelementptr inbounds ([5 x i8], [5 x i8]* @str, i32 0, i32 3)
|
||||
;
|
||||
%tmp3 = tail call i8* @strchr( i8* getelementptr ([5 x i8], [5 x i8]* @str, i32 0, i16 2), i16 103 ) ; <i8*> [#uses=1]
|
||||
ret i8* %tmp3
|
||||
}
|
||||
|
||||
; A 16-bit compatible strchr is not recognized as the standard library
|
||||
; function on 32-bit targets.
|
||||
declare i8* @strchr(i8*, i16)
|
||||
|
||||
define i8* @test2() {
|
||||
; CHECK32-LABEL: @test2(
|
||||
; CHECK32-NEXT: [[TMP3:%.*]] = tail call i8* @strchr(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @str1, i32 0, i32 2), i16 0)
|
||||
; CHECK32-NEXT: ret i8* [[TMP3]]
|
||||
;
|
||||
; CHECK16-LABEL: @test2(
|
||||
; CHECK16-NEXT: ret i8* getelementptr inbounds ([8 x i8], [8 x i8]* @str1, i32 0, i32 7)
|
||||
;
|
||||
%tmp3 = tail call i8* @strchr( i8* getelementptr ([8 x i8], [8 x i8]* @str1, i32 0, i32 2), i16 0 ) ; <i8*> [#uses=1]
|
||||
ret i8* %tmp3
|
||||
}
|
||||
|
||||
define i8* @test3() {
|
||||
; CHECK32-LABEL: @test3(
|
||||
; CHECK32-NEXT: entry:
|
||||
; CHECK32-NEXT: [[TMP3:%.*]] = tail call i8* @strchr(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @str2, i32 0, i32 1), i16 80)
|
||||
; CHECK32-NEXT: ret i8* [[TMP3]]
|
||||
;
|
||||
; CHECK16-LABEL: @test3(
|
||||
; CHECK16-NEXT: entry:
|
||||
; CHECK16-NEXT: ret i8* null
|
||||
;
|
||||
entry:
|
||||
%tmp3 = tail call i8* @strchr( i8* getelementptr ([5 x i8], [5 x i8]* @str2, i32 0, i32 1), i16 80 ) ; <i8*> [#uses=1]
|
||||
ret i8* %tmp3
|
||||
|
||||
}
|
||||
|
||||
@_2E_str = external constant [5 x i8] ; <[5 x i8]*> [#uses=1]
|
||||
|
||||
; A 16-bit compatible memcmp is not recognized as the standard library
|
||||
; function on 32-bit targets.
|
||||
declare i16 @memcmp(i8*, i8*, i16) nounwind readonly
|
||||
|
||||
define i1 @PR2341(i8** %start_addr) {
|
||||
; CHECK-LABEL: @PR2341(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = load i8*, i8** [[START_ADDR:%.*]], align 4
|
||||
; CHECK-NEXT: [[TMP5:%.*]] = call i16 @memcmp(i8* [[TMP4]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @_2E_str, i32 0, i32 0), i16 4) #[[ATTR0:[0-9]+]]
|
||||
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i16 [[TMP5]], 0
|
||||
; CHECK-NEXT: ret i1 [[TMP6]]
|
||||
;
|
||||
entry:
|
||||
%tmp4 = load i8*, i8** %start_addr, align 4 ; <i8*> [#uses=1]
|
||||
%tmp5 = call i16 @memcmp( i8* %tmp4, i8* getelementptr ([5 x i8], [5 x i8]* @_2E_str, i32 0, i32 0), i16 4 ) nounwind readonly ; <i32> [#uses=1]
|
||||
%tmp6 = icmp eq i16 %tmp5, 0 ; <i1> [#uses=1]
|
||||
ret i1 %tmp6
|
||||
|
||||
}
|
||||
|
||||
define i16 @PR4284() nounwind {
|
||||
; CHECK-LABEL: @PR4284(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[C0:%.*]] = alloca i8, align 1
|
||||
; CHECK-NEXT: [[C2:%.*]] = alloca i8, align 1
|
||||
; CHECK-NEXT: store i8 64, i8* [[C0]], align 1
|
||||
; CHECK-NEXT: store i8 -127, i8* [[C2]], align 1
|
||||
; CHECK-NEXT: [[CALL:%.*]] = call i16 @memcmp(i8* nonnull [[C0]], i8* nonnull [[C2]], i16 1)
|
||||
; CHECK-NEXT: ret i16 [[CALL]]
|
||||
;
|
||||
entry:
|
||||
%c0 = alloca i8, align 1 ; <i8*> [#uses=2]
|
||||
%c2 = alloca i8, align 1 ; <i8*> [#uses=2]
|
||||
store i8 64, i8* %c0
|
||||
store i8 -127, i8* %c2
|
||||
%call = call i16 @memcmp(i8* %c0, i8* %c2, i16 1) ; <i32> [#uses=1]
|
||||
ret i16 %call
|
||||
|
||||
}
|
||||
|
||||
%struct.__sFILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, i8*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64, %struct.pthread_mutex*, %struct.pthread*, i32, i32, %union.anon }
|
||||
%struct.__sbuf = type { i8*, i32, [4 x i8] }
|
||||
%struct.pthread = type opaque
|
||||
%struct.pthread_mutex = type opaque
|
||||
%union.anon = type { i64, [120 x i8] }
|
||||
@.str13 = external constant [2 x i8] ; <[2 x i8]*> [#uses=1]
|
||||
@.str14 = external constant [2 x i8] ; <[2 x i8]*> [#uses=1]
|
||||
|
||||
define i32 @PR4641(i32 %argc, i8** %argv, i1 %c1, i8* %ptr) nounwind {
|
||||
; CHECK-LABEL: @PR4641(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: call void @exit(i16 0) #[[ATTR1:[0-9]+]]
|
||||
; CHECK-NEXT: [[COND392:%.*]] = select i1 [[C1:%.*]], i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str13, i32 0, i32 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str14, i32 0, i32 0)
|
||||
; CHECK-NEXT: [[CALL393:%.*]] = call %struct.__sFILE* @fopen(i8* [[PTR:%.*]], i8* [[COND392]]) #[[ATTR1]]
|
||||
; CHECK-NEXT: unreachable
|
||||
;
|
||||
entry:
|
||||
call void @exit(i16 0) nounwind
|
||||
%cond392 = select i1 %c1, i8* getelementptr ([2 x i8], [2 x i8]* @.str13, i32 0, i32 0), i8* getelementptr ([2 x i8], [2 x i8]* @.str14, i32 0, i32 0) ; <i8*> [#uses=1]
|
||||
%call393 = call %struct.__sFILE* @fopen(i8* %ptr, i8* %cond392) nounwind ; <%struct.__sFILE*> [#uses=0]
|
||||
unreachable
|
||||
}
|
||||
|
||||
declare %struct.__sFILE* @fopen(i8*, i8*)
|
||||
|
||||
; A 16-bit compatible exit is not recognized as the standard library
|
||||
; function on 32-bit targets.
|
||||
declare void @exit(i16)
|
||||
|
||||
define i32 @PR4645(i1 %c1) {
|
||||
; CHECK-LABEL: @PR4645(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[IF_THEN:%.*]]
|
||||
; CHECK: lor.lhs.false:
|
||||
; CHECK-NEXT: br i1 [[C1:%.*]], label [[IF_THEN]], label [[FOR_COND:%.*]]
|
||||
; CHECK: if.then:
|
||||
; CHECK-NEXT: call void @exit(i16 1)
|
||||
; CHECK-NEXT: br label [[FOR_COND]]
|
||||
; CHECK: for.cond:
|
||||
; CHECK-NEXT: unreachable
|
||||
; CHECK: for.end:
|
||||
; CHECK-NEXT: br label [[FOR_COND]]
|
||||
;
|
||||
entry:
|
||||
br label %if.then
|
||||
|
||||
lor.lhs.false: ; preds = %while.body
|
||||
br i1 %c1, label %if.then, label %for.cond
|
||||
|
||||
if.then: ; preds = %lor.lhs.false, %while.body
|
||||
call void @exit(i16 1)
|
||||
br label %for.cond
|
||||
|
||||
for.cond: ; preds = %for.end, %if.then, %lor.lhs.false
|
||||
%j.0 = phi i32 [ %inc47, %for.end ], [ 0, %if.then ], [ 0, %lor.lhs.false ] ; <i32> [#uses=1]
|
||||
unreachable
|
||||
|
||||
for.end: ; preds = %for.cond20
|
||||
%inc47 = add i32 %j.0, 1 ; <i32> [#uses=1]
|
||||
br label %for.cond
|
||||
}
|
||||
|
||||
@h = constant [2 x i8] c"h\00" ; <[2 x i8]*> [#uses=1]
|
||||
@hel = constant [4 x i8] c"hel\00" ; <[4 x i8]*> [#uses=1]
|
||||
@hello_u = constant [8 x i8] c"hello_u\00" ; <[8 x i8]*> [#uses=1]
|
||||
|
||||
define i32 @MemCpy() {
|
||||
; CHECK-LABEL: @MemCpy(
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%h_p = getelementptr [2 x i8], [2 x i8]* @h, i32 0, i32 0
|
||||
%hel_p = getelementptr [4 x i8], [4 x i8]* @hel, i32 0, i32 0
|
||||
%hello_u_p = getelementptr [8 x i8], [8 x i8]* @hello_u, i32 0, i32 0
|
||||
%target = alloca [1024 x i8]
|
||||
%target_p = getelementptr [1024 x i8], [1024 x i8]* %target, i32 0, i32 0
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 %target_p, i8* align 2 %h_p, i16 2, i1 false)
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %target_p, i8* align 4 %hel_p, i16 4, i1 false)
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %target_p, i8* align 8 %hello_u_p, i16 8, i1 false)
|
||||
ret i32 0
|
||||
|
||||
}
|
||||
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i16, i1)
|
||||
|
||||
; A 16-bit compatible strcmp is not recognized as the standard library
|
||||
; function on 32-bit targets.
|
||||
declare i16 @strcmp(i8*, i8*) #0
|
||||
|
||||
define void @test9(i8* %x) {
|
||||
; CHECK32-LABEL: @test9(
|
||||
; CHECK32-NEXT: [[Y:%.*]] = call i16 @strcmp(i8* [[X:%.*]], i8* [[X]]) #[[ATTR5:[0-9]+]]
|
||||
; CHECK32-NEXT: ret void
|
||||
;
|
||||
; CHECK16-LABEL: @test9(
|
||||
; CHECK16-NEXT: ret void
|
||||
;
|
||||
%y = call i16 @strcmp(i8* %x, i8* %x) #1
|
||||
ret void
|
||||
}
|
||||
|
||||
; PR30484 - https://llvm.org/bugs/show_bug.cgi?id=30484
|
||||
; These aren't the library functions you're looking for...
|
||||
|
||||
declare i32 @isdigit(i8)
|
||||
declare i32 @isascii(i8)
|
||||
declare i32 @toascii(i8)
|
||||
|
||||
define i32 @fake_isdigit(i8 %x) {
|
||||
; CHECK-LABEL: @fake_isdigit(
|
||||
; CHECK-NEXT: [[Y:%.*]] = call i32 @isdigit(i8 [[X:%.*]])
|
||||
; CHECK-NEXT: ret i32 [[Y]]
|
||||
;
|
||||
%y = call i32 @isdigit(i8 %x)
|
||||
ret i32 %y
|
||||
}
|
||||
|
||||
define i32 @fake_isascii(i8 %x) {
|
||||
; CHECK-LABEL: @fake_isascii(
|
||||
; CHECK-NEXT: [[Y:%.*]] = call i32 @isascii(i8 [[X:%.*]])
|
||||
; CHECK-NEXT: ret i32 [[Y]]
|
||||
;
|
||||
%y = call i32 @isascii(i8 %x)
|
||||
ret i32 %y
|
||||
}
|
||||
|
||||
define i32 @fake_toascii(i8 %x) {
|
||||
; CHECK-LABEL: @fake_toascii(
|
||||
; CHECK-NEXT: [[Y:%.*]] = call i32 @toascii(i8 [[X:%.*]])
|
||||
; CHECK-NEXT: ret i32 [[Y]]
|
||||
;
|
||||
%y = call i32 @toascii(i8 %x)
|
||||
ret i32 %y
|
||||
}
|
||||
|
||||
declare double @pow(double, double)
|
||||
declare double @exp2(double)
|
||||
|
||||
; check to make sure only the correct libcall attributes are used
|
||||
define double @fake_exp2(double %x) {
|
||||
; CHECK-LABEL: @fake_exp2(
|
||||
; CHECK-NEXT: [[EXP2:%.*]] = call double @exp2(double [[X:%.*]])
|
||||
; CHECK-NEXT: ret double [[EXP2]]
|
||||
;
|
||||
|
||||
%y = call inreg double @pow(double inreg 2.0, double inreg %x)
|
||||
ret double %y
|
||||
}
|
||||
define double @fake_ldexp(i32 %x) {
|
||||
; CHECK32-LABEL: @fake_ldexp(
|
||||
; CHECK32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[X:%.*]])
|
||||
; CHECK32-NEXT: ret double [[LDEXP]]
|
||||
;
|
||||
; CHECK16-LABEL: @fake_ldexp(
|
||||
; CHECK16-NEXT: [[Y:%.*]] = sitofp i32 [[X:%.*]] to double
|
||||
; CHECK16-NEXT: [[Z:%.*]] = call inreg double @exp2(double [[Y]])
|
||||
; CHECK16-NEXT: ret double [[Z]]
|
||||
;
|
||||
|
||||
|
||||
%y = sitofp i32 %x to double
|
||||
%z = call inreg double @exp2(double %y)
|
||||
ret double %z
|
||||
}
|
||||
define double @fake_ldexp_16(i16 %x) {
|
||||
; CHECK32-LABEL: @fake_ldexp_16(
|
||||
; CHECK32-NEXT: [[TMP1:%.*]] = sext i16 [[X:%.*]] to i32
|
||||
; CHECK32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]])
|
||||
; CHECK32-NEXT: ret double [[LDEXP]]
|
||||
;
|
||||
; CHECK16-LABEL: @fake_ldexp_16(
|
||||
; CHECK16-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i16 [[X:%.*]])
|
||||
; CHECK16-NEXT: ret double [[LDEXP]]
|
||||
;
|
||||
|
||||
|
||||
%y = sitofp i16 %x to double
|
||||
%z = call inreg double @exp2(double %y)
|
||||
ret double %z
|
||||
}
|
||||
|
||||
; PR50885 - this would crash in ValueTracking.
|
||||
|
||||
; A 16-bit compatible snprintf is not recognized as the standard library
|
||||
; function on 32-bit targets.
|
||||
declare i16 @snprintf(i8*, double, i32*)
|
||||
|
||||
define i16 @fake_snprintf(i32 %buf, double %len, i32 * %str, i8* %ptr) {
|
||||
; CHECK-LABEL: @fake_snprintf(
|
||||
; CHECK-NEXT: [[CALL:%.*]] = call i16 @snprintf(i8* [[PTR:%.*]], double [[LEN:%.*]], i32* [[STR:%.*]])
|
||||
; CHECK-NEXT: ret i16 [[CALL]]
|
||||
;
|
||||
%call = call i16 @snprintf(i8* %ptr, double %len, i32* %str)
|
||||
ret i16 %call
|
||||
}
|
||||
|
||||
; Wrong return type for the real strlen.
|
||||
; https://llvm.org/PR50836
|
||||
|
||||
define i4 @strlen(i8* %s) {
|
||||
; CHECK-LABEL: @strlen(
|
||||
; CHECK-NEXT: [[R:%.*]] = call i4 @strlen(i8* [[S:%.*]])
|
||||
; CHECK-NEXT: ret i4 0
|
||||
;
|
||||
%r = call i4 @strlen(i8* %s)
|
||||
ret i4 0
|
||||
}
|
||||
|
||||
; Test emission of stpncpy.
|
||||
@a = dso_local global [4 x i8] c"123\00"
|
||||
@b = dso_local global [5 x i8] zeroinitializer
|
||||
declare i8* @__stpncpy_chk(i8* noundef, i8* noundef, i32 noundef, i32 noundef)
|
||||
define signext i32 @emit_stpncpy() {
|
||||
; CHECK-LABEL: @emit_stpncpy(
|
||||
; CHECK-NEXT: [[STPNCPY:%.*]] = call i8* @stpncpy(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @b, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @a, i32 0, i32 0), i32 2)
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%call = call i8* @__stpncpy_chk(i8* noundef getelementptr inbounds ([5 x i8], [5 x i8]* @b, i32 0, i32 0),
|
||||
i8* noundef getelementptr inbounds ([4 x i8], [4 x i8]* @a, i32 0, i32 0),
|
||||
i32 noundef 2, i32 noundef 5)
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
attributes #0 = { nobuiltin }
|
||||
attributes #1 = { builtin }
|
|
@ -5,13 +5,19 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
|
|||
|
||||
@G = constant [3 x i8] c"%s\00" ; <[3 x i8]*> [#uses=1]
|
||||
|
||||
; A 32-bit compatible sprintf is not recognized as the standard library
|
||||
; function on 16-bit targets.
|
||||
declare i32 @sprintf(i8*, i8*, ...)
|
||||
|
||||
define void @foo(i8* %P, i32* %X) {
|
||||
; CHECK-LABEL: @foo(
|
||||
; CHECK-NEXT: [[CSTR:%.*]] = bitcast i32* [[X:%.*]] to i8*
|
||||
; CHECK-NEXT: [[STRCPY:%.*]] = call i8* @strcpy(i8* noundef nonnull dereferenceable(1) [[P:%.*]], i8* noundef nonnull dereferenceable(1) [[CSTR]])
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK32-LABEL: @foo(
|
||||
; CHECK32-NEXT: [[CSTR:%.*]] = bitcast i32* [[X:%.*]] to i8*
|
||||
; CHECK32-NEXT: [[STRCPY:%.*]] = call i8* @strcpy(i8* noundef nonnull dereferenceable(1) [[P:%.*]], i8* noundef nonnull dereferenceable(1) [[CSTR]])
|
||||
; CHECK32-NEXT: ret void
|
||||
;
|
||||
; CHECK16-LABEL: @foo(
|
||||
; CHECK16-NEXT: [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* [[P:%.*]], i8* getelementptr inbounds ([3 x i8], [3 x i8]* @G, i32 0, i32 0), i32* [[X:%.*]])
|
||||
; CHECK16-NEXT: ret void
|
||||
;
|
||||
call i32 (i8*, i8*, ...) @sprintf( i8* %P, i8* getelementptr ([3 x i8], [3 x i8]* @G, i32 0, i32 0), i32* %X ) ; <i32>:1 [#uses=0]
|
||||
ret void
|
||||
|
@ -23,27 +29,42 @@ define void @foo(i8* %P, i32* %X) {
|
|||
@str2 = internal constant [5 x i8] c"Ponk\00"
|
||||
|
||||
define i8* @test1() {
|
||||
; CHECK-LABEL: @test1(
|
||||
; CHECK-NEXT: ret i8* getelementptr inbounds ([5 x i8], [5 x i8]* @str, i32 0, i32 3)
|
||||
; CHECK32-LABEL: @test1(
|
||||
; CHECK32-NEXT: ret i8* getelementptr inbounds ([5 x i8], [5 x i8]* @str, i32 0, i32 3)
|
||||
;
|
||||
; CHECK16-LABEL: @test1(
|
||||
; CHECK16-NEXT: [[TMP3:%.*]] = tail call i8* @strchr(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @str, i32 0, i32 2), i32 103)
|
||||
; CHECK16-NEXT: ret i8* [[TMP3]]
|
||||
;
|
||||
%tmp3 = tail call i8* @strchr( i8* getelementptr ([5 x i8], [5 x i8]* @str, i32 0, i32 2), i32 103 ) ; <i8*> [#uses=1]
|
||||
ret i8* %tmp3
|
||||
}
|
||||
|
||||
; A 32-bit compatible strchr is not recognized as the standard library
|
||||
; function on 16-bit targets.
|
||||
declare i8* @strchr(i8*, i32)
|
||||
|
||||
define i8* @test2() {
|
||||
; CHECK-LABEL: @test2(
|
||||
; CHECK-NEXT: ret i8* getelementptr inbounds ([8 x i8], [8 x i8]* @str1, i32 0, i32 7)
|
||||
; CHECK32-LABEL: @test2(
|
||||
; CHECK32-NEXT: ret i8* getelementptr inbounds ([8 x i8], [8 x i8]* @str1, i32 0, i32 7)
|
||||
;
|
||||
; CHECK16-LABEL: @test2(
|
||||
; CHECK16-NEXT: [[TMP3:%.*]] = tail call i8* @strchr(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @str1, i32 0, i32 2), i32 0)
|
||||
; CHECK16-NEXT: ret i8* [[TMP3]]
|
||||
;
|
||||
%tmp3 = tail call i8* @strchr( i8* getelementptr ([8 x i8], [8 x i8]* @str1, i32 0, i32 2), i32 0 ) ; <i8*> [#uses=1]
|
||||
ret i8* %tmp3
|
||||
}
|
||||
|
||||
define i8* @test3() {
|
||||
; CHECK-LABEL: @test3(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: ret i8* null
|
||||
; CHECK32-LABEL: @test3(
|
||||
; CHECK32-NEXT: entry:
|
||||
; CHECK32-NEXT: ret i8* null
|
||||
;
|
||||
; CHECK16-LABEL: @test3(
|
||||
; CHECK16-NEXT: entry:
|
||||
; CHECK16-NEXT: [[TMP3:%.*]] = tail call i8* @strchr(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @str2, i32 0, i32 1), i32 80)
|
||||
; CHECK16-NEXT: ret i8* [[TMP3]]
|
||||
;
|
||||
entry:
|
||||
%tmp3 = tail call i8* @strchr( i8* getelementptr ([5 x i8], [5 x i8]* @str2, i32 0, i32 1), i32 80 ) ; <i8*> [#uses=1]
|
||||
|
@ -53,15 +74,24 @@ entry:
|
|||
|
||||
@_2E_str = external constant [5 x i8] ; <[5 x i8]*> [#uses=1]
|
||||
|
||||
; A 32-bit compatible memcmp is not recognized as the standard library
|
||||
; function on 16-bit targets.
|
||||
declare i32 @memcmp(i8*, i8*, i32) nounwind readonly
|
||||
|
||||
define i1 @PR2341(i8** %start_addr) {
|
||||
; CHECK-LABEL: @PR2341(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = load i8*, i8** [[START_ADDR:%.*]], align 4
|
||||
; CHECK-NEXT: [[TMP5:%.*]] = call i32 @memcmp(i8* noundef nonnull dereferenceable(4) [[TMP4]], i8* noundef nonnull dereferenceable(4) getelementptr inbounds ([5 x i8], [5 x i8]* @_2E_str, i32 0, i32 0), i32 4) #[[ATTR0:[0-9]+]]
|
||||
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
|
||||
; CHECK-NEXT: ret i1 [[TMP6]]
|
||||
; CHECK32-LABEL: @PR2341(
|
||||
; CHECK32-NEXT: entry:
|
||||
; CHECK32-NEXT: [[TMP4:%.*]] = load i8*, i8** [[START_ADDR:%.*]], align 4
|
||||
; CHECK32-NEXT: [[TMP5:%.*]] = call i32 @memcmp(i8* noundef nonnull dereferenceable(4) [[TMP4]], i8* noundef nonnull dereferenceable(4) getelementptr inbounds ([5 x i8], [5 x i8]* @_2E_str, i32 0, i32 0), i32 4) #[[ATTR0:[0-9]+]]
|
||||
; CHECK32-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
|
||||
; CHECK32-NEXT: ret i1 [[TMP6]]
|
||||
;
|
||||
; CHECK16-LABEL: @PR2341(
|
||||
; CHECK16-NEXT: entry:
|
||||
; CHECK16-NEXT: [[TMP4:%.*]] = load i8*, i8** [[START_ADDR:%.*]], align 4
|
||||
; CHECK16-NEXT: [[TMP5:%.*]] = call i32 @memcmp(i8* [[TMP4]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @_2E_str, i32 0, i32 0), i32 4) #[[ATTR0:[0-9]+]]
|
||||
; CHECK16-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
|
||||
; CHECK16-NEXT: ret i1 [[TMP6]]
|
||||
;
|
||||
entry:
|
||||
%tmp4 = load i8*, i8** %start_addr, align 4 ; <i8*> [#uses=1]
|
||||
|
@ -72,9 +102,18 @@ entry:
|
|||
}
|
||||
|
||||
define i32 @PR4284() nounwind {
|
||||
; CHECK-LABEL: @PR4284(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: ret i32 -65
|
||||
; CHECK32-LABEL: @PR4284(
|
||||
; CHECK32-NEXT: entry:
|
||||
; CHECK32-NEXT: ret i32 -65
|
||||
;
|
||||
; CHECK16-LABEL: @PR4284(
|
||||
; CHECK16-NEXT: entry:
|
||||
; CHECK16-NEXT: [[C0:%.*]] = alloca i8, align 1
|
||||
; CHECK16-NEXT: [[C2:%.*]] = alloca i8, align 1
|
||||
; CHECK16-NEXT: store i8 64, i8* [[C0]], align 1
|
||||
; CHECK16-NEXT: store i8 -127, i8* [[C2]], align 1
|
||||
; CHECK16-NEXT: [[CALL:%.*]] = call i32 @memcmp(i8* nonnull [[C0]], i8* nonnull [[C2]], i32 1)
|
||||
; CHECK16-NEXT: ret i32 [[CALL]]
|
||||
;
|
||||
entry:
|
||||
%c0 = alloca i8, align 1 ; <i8*> [#uses=2]
|
||||
|
@ -111,6 +150,8 @@ entry:
|
|||
|
||||
declare %struct.__sFILE* @fopen(i8*, i8*)
|
||||
|
||||
; A 32-bit compatible exit is not recognized as the standard library
|
||||
; function on 16-bit targets.
|
||||
declare void @exit(i32)
|
||||
|
||||
define i32 @PR4645(i1 %c1) {
|
||||
|
@ -168,11 +209,17 @@ define i32 @MemCpy() {
|
|||
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind
|
||||
|
||||
; A 32-bit compatible strcmp is not recognized as the standard library
|
||||
; function on 16-bit targets.
|
||||
declare i32 @strcmp(i8*, i8*) #0
|
||||
|
||||
define void @test9(i8* %x) {
|
||||
; CHECK-LABEL: @test9(
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK32-LABEL: @test9(
|
||||
; CHECK32-NEXT: ret void
|
||||
;
|
||||
; CHECK16-LABEL: @test9(
|
||||
; CHECK16-NEXT: [[Y:%.*]] = call i32 @strcmp(i8* [[X:%.*]], i8* [[X]]) #[[ATTR5:[0-9]+]]
|
||||
; CHECK16-NEXT: ret void
|
||||
;
|
||||
%y = call i32 @strcmp(i8* %x, i8* %x) #1
|
||||
ret void
|
||||
|
@ -260,6 +307,8 @@ define double @fake_ldexp_16(i16 %x) {
|
|||
|
||||
; PR50885 - this would crash in ValueTracking.
|
||||
|
||||
; A 32-bit compatible snprintf is not recognized as the standard library
|
||||
; function on 16-bit targets.
|
||||
declare i32 @snprintf(i8*, double, i32*)
|
||||
|
||||
define i32 @fake_snprintf(i32 %buf, double %len, i32 * %str, i8* %ptr) {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
; Regression test for PR51200.
|
||||
;
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
|
||||
;
|
||||
; This transformation requires the pointer size, as it assumes that size_t is
|
||||
; the size of a pointer.
|
||||
|
||||
@percent_s = constant [3 x i8] c"%s\00"
|
||||
|
||||
declare i32 @sprintf(i8**, i32*, ...)
|
||||
|
||||
define i32 @PR51200(i8** %p, i32* %p2) {
|
||||
; CHECK-LABEL: @PR51200(
|
||||
; Don't check anything, just expect the test to compile successfully.
|
||||
;
|
||||
%call = call i32 (i8**, i32*, ...) @sprintf(i8** %p, i32* bitcast ([3 x i8]* @percent_s to i32*), i32* %p2)
|
||||
ret i32 %call
|
||||
}
|
|
@ -25,19 +25,20 @@ entry:
|
|||
|
||||
declare float @llvm.sqrt.f32(float) #1
|
||||
|
||||
; FIXME:
|
||||
; This is a function called "sqrtf", but its type is double.
|
||||
; Assume it is a user function rather than a libm function,
|
||||
; so don't transform it.
|
||||
; The call below is to a function called "sqrtf", but its type is double.
|
||||
; Assume it is a user function rather than a libm function, and so don't
|
||||
; transform it.
|
||||
|
||||
define double @fake_sqrt(double %a, double %b) {
|
||||
; CHECK-LABEL: @fake_sqrt(
|
||||
; CHECK-NEXT: [[FABS:%.*]] = call fast double @llvm.fabs.f64(double [[A:%.*]])
|
||||
; CHECK-NEXT: ret double [[FABS]]
|
||||
; CHECK-NEXT: [[C:%.*]] = fmul fast double [[A:%.*]], [[A]]
|
||||
; CHECK-NEXT: [[E:%.*]] = call fast double @sqrtf(double [[C]]) #[[ATTR1:[0-9]+]]
|
||||
; CHECK-NEXT: ret double [[E]]
|
||||
;
|
||||
%c = fmul fast double %a, %a
|
||||
%e = call fast double @sqrtf(double %c) readnone
|
||||
ret double %e
|
||||
}
|
||||
|
||||
declare double @sqrtf(double) readnone ; This is not the 'sqrt' you're looking for.
|
||||
; Standard sqrtf takes and returns float. The following is not it.
|
||||
declare double @sqrtf(double) readnone
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
; Verify that calls to known stdio library functions declared with
|
||||
; incompatible signatures are handled gracefully and without aborting.
|
||||
;
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -passes=instcombine -opaque-pointers -S | FileCheck %s
|
||||
|
||||
declare i32 @fwrite(i8*, i64, i64, ptr)
|
||||
declare i8 @fputc(ptr, ptr)
|
||||
|
||||
declare void @printf(ptr)
|
||||
declare i8 @fprintf(ptr, ptr)
|
||||
declare i8 @sprintf(ptr, ptr)
|
||||
|
||||
|
||||
@ca1 = constant [1 x i8] c"1"
|
||||
@pcnt_s = constant [3 x i8] c"%s\00"
|
||||
|
||||
|
||||
; Verify that a call to fwrite isn't transformed into one to fputc when
|
||||
; the latter is declared with an incompatible signature (which might
|
||||
; trigger an abort).
|
||||
|
||||
define void @call_fwrite(ptr %fp) {
|
||||
%p = getelementptr [1 x i8], ptr @ca1, i32 0, i32 0
|
||||
call i32 @fwrite(ptr %p, i64 1, i64 1, ptr %fp)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
; Verify that a call to an incompatible void printf(char*) with just "%s"
|
||||
; isn't transformed.
|
||||
|
||||
define void @call_printf(ptr %s) {
|
||||
; CHECK-LABEL: @call_printf(
|
||||
;
|
||||
%fmt = getelementptr [3 x i8], ptr @pcnt_s, i32 0, i32 0
|
||||
call i32 @printf(ptr %fmt)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Verify that a call to an incompatible int fprintf(FILE*, char*) isn't
|
||||
; transformed.
|
||||
|
||||
define i8 @call_fprintf(ptr %fp, ptr %p) {
|
||||
; CHECK-LABEL: @call_fprintf(
|
||||
;
|
||||
%fmt = getelementptr [3 x i8], ptr @pcnt_s, i32 0, i32 0
|
||||
%call = call i8 (ptr, ptr, ...) @fprintf(ptr %fp, ptr %fmt, ptr %p)
|
||||
ret i8 %call
|
||||
}
|
||||
|
||||
; Verify that a call to an incompatible int sprintf(FILE*, char*) isn't
|
||||
; transformed.
|
||||
|
||||
define i8 @call_sprintf(ptr %p, ptr %q) {
|
||||
; CHECK-LABEL: @call_sprintf(
|
||||
;
|
||||
%fmt = getelementptr [3 x i8], ptr @pcnt_s, i32 0, i32 0
|
||||
%call = call i8 (ptr, ptr, ...) @sprintf(ptr %p, ptr %fmt, ptr %q)
|
||||
ret i8 %call
|
||||
}
|
||||
|
|
@ -11,7 +11,6 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
|
|||
@b = common global [32 x i8] zeroinitializer, align 1
|
||||
@percent_s = constant [3 x i8] c"%s\00"
|
||||
|
||||
declare i32 @sprintf(i8**, i32*, ...)
|
||||
declare i8* @stpcpy(i8*, i8*)
|
||||
|
||||
define i8* @test_simplify1() {
|
||||
|
@ -76,21 +75,3 @@ define i8* @test_no_incompatible_attr() {
|
|||
%ret = call dereferenceable(1) i8* @stpcpy(i8* %dst, i8* %src)
|
||||
ret i8* %ret
|
||||
}
|
||||
|
||||
; The libcall prototype checker does not check for exact pointer type
|
||||
; (just pointer of some type), so we identify this as a standard sprintf
|
||||
; call. This requires a cast to operate on mismatched pointer types.
|
||||
|
||||
define i32 @PR51200(i8** %p, i32* %p2) {
|
||||
; CHECK-LABEL: @PR51200(
|
||||
; CHECK-NEXT: [[CSTR:%.*]] = bitcast i8** [[P:%.*]] to i8*
|
||||
; CHECK-NEXT: [[CSTR1:%.*]] = bitcast i32* [[P2:%.*]] to i8*
|
||||
; CHECK-NEXT: [[STPCPY:%.*]] = call i8* @stpcpy(i8* [[CSTR]], i8* [[CSTR1]])
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint i8* [[STPCPY]] to i32
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint i8** [[P]] to i32
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = sub i32 [[TMP1]], [[TMP2]]
|
||||
; CHECK-NEXT: ret i32 [[TMP3]]
|
||||
;
|
||||
%call = call i32 (i8**, i32*, ...) @sprintf(i8** %p, i32* bitcast ([3 x i8]* @percent_s to i32*), i32* %p2)
|
||||
ret i32 %call
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
|
|||
@hello = constant [6 x i8] c"hello\00"
|
||||
@a = common global [32 x i8] zeroinitializer, align 1
|
||||
|
||||
declare i16* @stpcpy(i8*, i8*)
|
||||
declare i16 @stpcpy(i8*, i8*)
|
||||
|
||||
define void @test_no_simplify1() {
|
||||
; CHECK-LABEL: @test_no_simplify1(
|
||||
|
@ -16,7 +16,7 @@ define void @test_no_simplify1() {
|
|||
%dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
|
||||
%src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
|
||||
|
||||
call i16* @stpcpy(i8* %dst, i8* %src)
|
||||
; CHECK: call i16* @stpcpy
|
||||
call i16 @stpcpy(i8* %dst, i8* %src)
|
||||
; CHECK: call i16 @stpcpy
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@ define void @test_no_simplify() {
|
|||
%dst = getelementptr inbounds [60 x i16], [60 x i16]* @a, i32 0, i32 0
|
||||
%src = getelementptr inbounds [8 x i8], [8 x i8]* @.str, i32 0, i32 0
|
||||
|
||||
; CHECK-NEXT: call i16* @__strcpy_chk
|
||||
call i16* @__strcpy_chk(i16* %dst, i8* %src, i32 8)
|
||||
; 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)
|
||||
declare i16 @__strcpy_chk(i16*, i8*, i32)
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
declare i32 @strtol(i8*, i8**, i32)
|
||||
declare i32 @atoi(i8*)
|
||||
declare i32 @atol(i8*)
|
||||
declare i32 @atoll(i8*)
|
||||
declare i32 @strtoll(i8*, i8**, i32)
|
||||
declare i64 @atoll(i8*)
|
||||
declare i64 @strtoll(i8*, i8**, i32)
|
||||
|
||||
define i32 @strtol_dec() #0 {
|
||||
; CHECK-LABEL: @strtol_dec(
|
||||
|
@ -128,21 +128,19 @@ define i32 @atol_test() #0 {
|
|||
ret i32 %call
|
||||
}
|
||||
|
||||
define i32 @atoll_test() #0 {
|
||||
define i64 @atoll_test() #0 {
|
||||
; CHECK-LABEL: @atoll_test(
|
||||
; CHECK-NEXT: [[CALL:%.*]] = call i32 @atoll(i8* nocapture getelementptr inbounds ([11 x i8], [11 x i8]* @.str.5, i64 0, i64 0))
|
||||
; CHECK-NEXT: ret i32 [[CALL]]
|
||||
; CHECK-NEXT: ret i64 4994967295
|
||||
;
|
||||
%call = call i32 @atoll(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.5, i32 0, i32 0)) #3
|
||||
ret i32 %call
|
||||
%call = call i64 @atoll(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.5, i32 0, i32 0)) #3
|
||||
ret i64 %call
|
||||
}
|
||||
|
||||
define i32 @strtoll_test() #0 {
|
||||
define i64 @strtoll_test() #0 {
|
||||
; CHECK-LABEL: @strtoll_test(
|
||||
; CHECK-NEXT: [[CALL:%.*]] = call i32 @strtoll(i8* nocapture getelementptr inbounds ([11 x i8], [11 x i8]* @.str.7, i64 0, i64 0), i8** null, i32 10)
|
||||
; CHECK-NEXT: ret i32 [[CALL]]
|
||||
; CHECK-NEXT: ret i64 4994967295
|
||||
;
|
||||
; CHECK-NEXT
|
||||
%call = call i32 @strtoll(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.7, i32 0, i32 0), i8** null, i32 10) #5
|
||||
ret i32 %call
|
||||
%call = call i64 @strtoll(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.7, i32 0, i32 0), i8** null, i32 10) #5
|
||||
ret i64 %call
|
||||
}
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
; Verify that calls to known string library functions declared with
|
||||
; incompatible signatures are handled gracefully and without aborting.
|
||||
;
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -passes=instcombine -opaque-pointers -S | FileCheck %s
|
||||
|
||||
@a = constant [2 x i8] c"1\00"
|
||||
|
||||
declare ptr @atoi(ptr)
|
||||
declare ptr @atol(ptr)
|
||||
declare ptr @atoll(ptr)
|
||||
|
||||
define void @call_bad_ato(ptr %ps) {
|
||||
; CHECK-LABEL: @call_bad_ato(
|
||||
; CHECK-NEXT: [[IR:%.*]] = call ptr @atoi(ptr nonnull @a)
|
||||
; CHECK-NEXT: store ptr [[IR]], ptr [[PS:%.*]], align 8
|
||||
; CHECK-NEXT: [[LR:%.*]] = call ptr @atol(ptr nonnull @a)
|
||||
; CHECK-NEXT: [[PS1:%.*]] = getelementptr ptr, ptr [[PS]], i64 1
|
||||
; CHECK-NEXT: store ptr [[LR]], ptr [[PS1]], align 8
|
||||
; CHECK-NEXT: [[LLR:%.*]] = call ptr @atol(ptr nonnull @a)
|
||||
; CHECK-NEXT: [[PS2:%.*]] = getelementptr ptr, ptr [[PS]], i64 2
|
||||
; CHECK-NEXT: store ptr [[LLR]], ptr [[PS2]], align 8
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%p = getelementptr [2 x i8], [2 x i8]* @a, i32 0, i32 0
|
||||
|
||||
%ir = call ptr @atoi(ptr %p)
|
||||
%ps0 = getelementptr ptr, ptr %ps, i32 0
|
||||
store ptr %ir, ptr %ps0
|
||||
|
||||
%lr = call ptr @atol(ptr %p)
|
||||
%ps1 = getelementptr ptr, ptr %ps, i32 1
|
||||
store ptr %lr, ptr %ps1
|
||||
|
||||
%llr = call ptr @atol(ptr %p)
|
||||
%ps2 = getelementptr ptr, ptr %ps, i32 2
|
||||
store ptr %llr, ptr %ps2
|
||||
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
declare ptr @strncasecmp(ptr, ptr)
|
||||
|
||||
define ptr @call_bad_strncasecmp() {
|
||||
; CHECK-LABEL: @call_bad_strncasecmp(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = call ptr @strncasecmp(ptr nonnull @a, ptr getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1))
|
||||
; CHECK-NEXT: ret ptr [[CMP]]
|
||||
;
|
||||
%p0 = getelementptr [2 x i8], [2 x i8]* @a, i32 0, i32 0
|
||||
%p1 = getelementptr [2 x i8], [2 x i8]* @a, i32 0, i32 1
|
||||
%cmp = call ptr @strncasecmp(ptr %p0, ptr %p1)
|
||||
ret ptr %cmp
|
||||
}
|
||||
|
||||
|
||||
declare i1 @strcoll(ptr, ptr, ptr)
|
||||
|
||||
define i1 @call_bad_strcoll() {
|
||||
; CHECK-LABEL: @call_bad_strcoll(
|
||||
; CHECK-NEXT: [[I:%.*]] = call i1 @strcoll(ptr nonnull @a, ptr getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1), ptr nonnull @a)
|
||||
; CHECK-NEXT: ret i1 [[I]]
|
||||
;
|
||||
%p0 = getelementptr [2 x i8], [2 x i8]* @a, i32 0, i32 0
|
||||
%p1 = getelementptr [2 x i8], [2 x i8]* @a, i32 0, i32 1
|
||||
%i = call i1 @strcoll(ptr %p0, ptr %p1, ptr %p0)
|
||||
ret i1 %i
|
||||
}
|
||||
|
||||
|
||||
declare ptr @strndup(ptr)
|
||||
|
||||
define ptr @call_bad_strndup() {
|
||||
; CHECK-LABEL: @call_bad_strndup(
|
||||
; CHECK-NEXT: [[D:%.*]] = call ptr @strndup(ptr nonnull @a)
|
||||
; CHECK-NEXT: ret ptr [[D]]
|
||||
;
|
||||
%p = getelementptr [2 x i8], [2 x i8]* @a, i32 0, i32 0
|
||||
%d = call ptr @strndup(ptr %p)
|
||||
ret ptr %d
|
||||
}
|
||||
|
||||
|
||||
declare i1 @strtok(ptr, ptr, i1)
|
||||
|
||||
define i1 @call_bad_strtok() {
|
||||
; CHECK-LABEL: @call_bad_strtok(
|
||||
; CHECK-NEXT: [[RET:%.*]] = call i1 @strtok(ptr nonnull @a, ptr getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1), i1 false)
|
||||
; CHECK-NEXT: ret i1 [[RET]]
|
||||
;
|
||||
%p0 = getelementptr [2 x i8], [2 x i8]* @a, i32 0, i32 0
|
||||
%p1 = getelementptr [2 x i8], [2 x i8]* @a, i32 0, i32 1
|
||||
%ret = call i1 @strtok(ptr %p0, ptr %p1, i1 0)
|
||||
ret i1 %ret
|
||||
}
|
||||
|
||||
|
||||
|
||||
declare i1 @strtok_r(ptr, ptr)
|
||||
|
||||
define i1 @call_bad_strtok_r() {
|
||||
; CHECK-LABEL: @call_bad_strtok_r(
|
||||
; CHECK-NEXT: [[RET:%.*]] = call i1 @strtok_r(ptr nonnull @a, ptr getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1))
|
||||
; CHECK-NEXT: ret i1 [[RET]]
|
||||
;
|
||||
%p0 = getelementptr [2 x i8], [2 x i8]* @a, i32 0, i32 0
|
||||
%p1 = getelementptr [2 x i8], [2 x i8]* @a, i32 0, i32 1
|
||||
%ret = call i1 @strtok_r(ptr %p0, ptr %p1)
|
||||
ret i1 %ret
|
||||
}
|
||||
|
||||
|
||||
declare i32 @strtol(ptr, ptr)
|
||||
declare i32 @strtoul(ptr, ptr)
|
||||
|
||||
declare i64 @strtoll(ptr, ptr)
|
||||
declare i64 @strtoull(ptr, ptr)
|
||||
|
||||
define void @call_bad_strto(i32* %psi32, i64* %psi64) {
|
||||
; CHECK-LABEL: @call_bad_strto(
|
||||
; CHECK-NEXT: [[LR:%.*]] = call i32 @strtol(ptr nonnull @a, ptr null)
|
||||
; CHECK-NEXT: store i32 [[LR]], ptr [[PSI32:%.*]], align 4
|
||||
; CHECK-NEXT: [[ULR:%.*]] = call i32 @strtoul(ptr nonnull @a, ptr null)
|
||||
; CHECK-NEXT: [[PS1:%.*]] = getelementptr i32, ptr [[PSI32]], i64 1
|
||||
; CHECK-NEXT: store i32 [[ULR]], ptr [[PS1]], align 4
|
||||
; CHECK-NEXT: [[LLR:%.*]] = call i64 @strtoll(ptr nonnull @a, ptr null)
|
||||
; CHECK-NEXT: store i64 [[LLR]], ptr [[PSI64:%.*]], align 4
|
||||
; CHECK-NEXT: [[ULLR:%.*]] = call i64 @strtoull(ptr nonnull @a, ptr null)
|
||||
; CHECK-NEXT: [[PS3:%.*]] = getelementptr i64, ptr [[PSI64]], i64 3
|
||||
; CHECK-NEXT: store i64 [[ULLR]], ptr [[PS3]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%p = getelementptr [2 x i8], [2 x i8]* @a, i32 0, i32 0
|
||||
|
||||
%lr = call i32 @strtol(ptr %p, ptr null)
|
||||
%ps0 = getelementptr i32, i32* %psi32, i32 0
|
||||
store i32 %lr, i32* %ps0
|
||||
|
||||
%ulr = call i32 @strtoul(ptr %p, ptr null)
|
||||
%ps1 = getelementptr i32, i32* %psi32, i32 1
|
||||
store i32 %ulr, i32* %ps1
|
||||
|
||||
%llr = call i64 @strtoll(ptr %p, ptr null)
|
||||
%ps2 = getelementptr i64, i64* %psi64, i32 0
|
||||
store i64 %llr, i64* %ps2
|
||||
|
||||
%ullr = call i64 @strtoull(ptr %p, ptr null)
|
||||
%ps3 = getelementptr i64, i64* %psi64, i32 3
|
||||
store i64 %ullr, i64* %ps3
|
||||
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
declare ptr @strxfrm(ptr, ptr)
|
||||
|
||||
define ptr @call_bad_strxfrm() {
|
||||
; CHECK-LABEL: @call_bad_strxfrm(
|
||||
; CHECK-NEXT: [[RET:%.*]] = call ptr @strxfrm(ptr nonnull @a, ptr getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1))
|
||||
; CHECK-NEXT: ret ptr [[RET]]
|
||||
;
|
||||
%p0 = getelementptr [2 x i8], [2 x i8]* @a, i32 0, i32 0
|
||||
%p1 = getelementptr [2 x i8], [2 x i8]* @a, i32 0, i32 1
|
||||
%ret = call ptr @strxfrm(ptr %p0, ptr %p1)
|
||||
ret ptr %ret
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
; Test that the strcat libcall simplifier works correctly.
|
||||
; Test that the strcat folder avoids simplifying a call to the function
|
||||
; declared with an incompatible type.
|
||||
;
|
||||
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
|
||||
|
||||
|
@ -8,15 +9,16 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
|
|||
@empty = constant [1 x i8] c"\00"
|
||||
@a = common global [32 x i8] zeroinitializer, align 1
|
||||
|
||||
declare i16* @strcat(i8*, i8*)
|
||||
; Expected type: i8* @strcat(i8*, i8*).
|
||||
declare i16 @strcat(i8*, i8*)
|
||||
|
||||
define void @test_nosimplify1() {
|
||||
; CHECK-LABEL: @test_nosimplify1(
|
||||
; CHECK: call i16* @strcat
|
||||
; CHECK: call i16 @strcat
|
||||
; CHECK: ret void
|
||||
|
||||
%dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
|
||||
%src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
|
||||
call i16* @strcat(i8* %dst, i8* %src)
|
||||
call i16 @strcat(i8* %dst, i8* %src)
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
; Test that the strcpy library call simplifier works correctly.
|
||||
; Test that the strcpy folder avoids simplifying a call to the function
|
||||
; declared with an incompatible type.
|
||||
;
|
||||
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
|
||||
;
|
||||
; This transformation requires the pointer size, as it assumes that size_t is
|
||||
|
@ -8,7 +10,8 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
|
|||
@hello = constant [6 x i8] c"hello\00"
|
||||
@a = common global [32 x i8] zeroinitializer, align 1
|
||||
|
||||
declare i16* @strcpy(i8*, i8*)
|
||||
; Expected type: i8* @strcpy(i8*, i8*)
|
||||
declare i16 @strcpy(i8*, i8*)
|
||||
|
||||
define void @test_no_simplify1() {
|
||||
; CHECK-LABEL: @test_no_simplify1(
|
||||
|
@ -16,7 +19,7 @@ define void @test_no_simplify1() {
|
|||
%dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
|
||||
%src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
|
||||
|
||||
call i16* @strcpy(i8* %dst, i8* %src)
|
||||
; CHECK: call i16* @strcpy
|
||||
call i16 @strcpy(i8* %dst, i8* %src)
|
||||
; CHECK: call i16 @strcpy
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@ define void @test_no_simplify() {
|
|||
%dst = getelementptr inbounds [60 x i16], [60 x i16]* @a, i32 0, i32 0
|
||||
%src = getelementptr inbounds [8 x i8], [8 x i8]* @.str, i32 0, i32 0
|
||||
|
||||
; CHECK-NEXT: call i16* @__strcpy_chk
|
||||
call i16* @__strcpy_chk(i16* %dst, i8* %src, i32 8)
|
||||
; 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)
|
||||
declare i16 @__strcpy_chk(i16*, i8*, i32)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; Test that the strncat libcall simplifier works correctly.
|
||||
; Test that the strncat folder avoids simplifying a call to the function
|
||||
; declared with an incompatible type.
|
||||
;
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; 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"
|
||||
|
@ -9,16 +10,16 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
|
|||
@empty = constant [1 x i8] c"\00"
|
||||
@a = common global [32 x i8] zeroinitializer, align 1
|
||||
|
||||
declare i16* @strncat(i8*, i8*, i32)
|
||||
declare i16 @strncat(i8*, i8*, i32)
|
||||
|
||||
define void @test_nosimplify1() {
|
||||
; CHECK-LABEL: @test_nosimplify1(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call i16* @strncat(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 13)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call i16 @strncat(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 13)
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
||||
%dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
|
||||
%src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
|
||||
call i16* @strncat(i8* %dst, i8* %src, i32 13)
|
||||
call i16 @strncat(i8* %dst, i8* %src, i32 13)
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
; Test that the strncpy folder avoids simplifying a call to the function
|
||||
; declared with an incompatible type.
|
||||
;
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; Test that the strncpy library call simplifier works correctly.
|
||||
;
|
||||
|
@ -8,18 +11,18 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
|
|||
@hello = constant [6 x i8] c"hello\00"
|
||||
@a = common global [32 x i8] zeroinitializer, align 1
|
||||
|
||||
declare i16* @strncpy(i8*, i8*, i32)
|
||||
declare i16 @strncpy(i8*, i8*, i32)
|
||||
|
||||
; Check that 'strncpy' functions with the wrong prototype aren't simplified.
|
||||
|
||||
define void @test_no_simplify1() {
|
||||
; CHECK-LABEL: @test_no_simplify1(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call i16* @strncpy(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call i16 @strncpy(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6)
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
|
||||
%src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
|
||||
|
||||
call i16* @strncpy(i8* %dst, i8* %src, i32 6)
|
||||
call i16 @strncpy(i8* %dst, i8* %src, i32 6)
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@ define void @test_no_simplify() {
|
|||
%dst = getelementptr inbounds [60 x i16], [60 x i16]* @a, i32 0, i32 0
|
||||
%src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0
|
||||
|
||||
; CHECK-NEXT: call i16* @__strncpy_chk
|
||||
call i16* @__strncpy_chk(i16* %dst, i8* %src, i32 60, i32 60)
|
||||
; CHECK-NEXT: call i16 @__strncpy_chk
|
||||
call i16 @__strncpy_chk(i16* %dst, i8* %src, i32 60, i32 60)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i16* @__strncpy_chk(i16*, i8*, i32, i32)
|
||||
declare i16 @__strncpy_chk(i16*, i8*, i32, i32)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
@hello = constant [6 x i8] c"hello\00"
|
||||
@null = constant [1 x i8] zeroinitializer
|
||||
|
||||
declare i8* @strndup(i8*, i32)
|
||||
declare i8* @strndup(i8*, i64)
|
||||
|
||||
define i8* @test1() {
|
||||
; CHECK-LABEL: @test1(
|
||||
|
@ -12,17 +12,17 @@ define i8* @test1() {
|
|||
; CHECK-NEXT: ret i8* [[STRDUP]]
|
||||
;
|
||||
%src = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0
|
||||
%ret = call i8* @strndup(i8* %src, i32 0)
|
||||
%ret = call i8* @strndup(i8* %src, i64 0)
|
||||
ret i8* %ret
|
||||
}
|
||||
|
||||
define i8* @test2() {
|
||||
; CHECK-LABEL: @test2(
|
||||
; CHECK-NEXT: [[RET:%.*]] = call dereferenceable_or_null(5) i8* @strndup(i8* dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i64 0, i64 0), i32 4)
|
||||
; CHECK-NEXT: [[RET:%.*]] = call dereferenceable_or_null(5) i8* @strndup(i8* dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i64 0, i64 0), i64 4)
|
||||
; CHECK-NEXT: ret i8* [[RET]]
|
||||
;
|
||||
%src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
|
||||
%ret = call i8* @strndup(i8* %src, i32 4)
|
||||
%ret = call i8* @strndup(i8* %src, i64 4)
|
||||
ret i8* %ret
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ define i8* @test3() {
|
|||
; CHECK-NEXT: ret i8* [[STRDUP]]
|
||||
;
|
||||
%src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
|
||||
%ret = call i8* @strndup(i8* %src, i32 5)
|
||||
%ret = call i8* @strndup(i8* %src, i64 5)
|
||||
ret i8* %ret
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ define i8* @test4() {
|
|||
; CHECK-NEXT: ret i8* [[STRDUP]]
|
||||
;
|
||||
%src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
|
||||
%ret = call i8* @strndup(i8* %src, i32 6)
|
||||
%ret = call i8* @strndup(i8* %src, i64 6)
|
||||
ret i8* %ret
|
||||
}
|
||||
|
||||
|
@ -52,16 +52,16 @@ define i8* @test5() {
|
|||
; CHECK-NEXT: ret i8* [[STRDUP]]
|
||||
;
|
||||
%src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
|
||||
%ret = call i8* @strndup(i8* %src, i32 7)
|
||||
%ret = call i8* @strndup(i8* %src, i64 7)
|
||||
ret i8* %ret
|
||||
}
|
||||
|
||||
define i8* @test6(i32 %n) {
|
||||
define i8* @test6(i64 %n) {
|
||||
; CHECK-LABEL: @test6(
|
||||
; CHECK-NEXT: [[RET:%.*]] = call i8* @strndup(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i64 0, i64 0), i32 [[N:%.*]])
|
||||
; CHECK-NEXT: [[RET:%.*]] = call i8* @strndup(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i64 0, i64 0), i64 [[N:%.*]])
|
||||
; CHECK-NEXT: ret i8* [[RET]]
|
||||
;
|
||||
%src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
|
||||
%ret = call i8* @strndup(i8* %src, i32 %n)
|
||||
%ret = call i8* @strndup(i8* %src, i64 %n)
|
||||
ret i8* %ret
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
; Test that the strpbrk library call simplifier works correctly.
|
||||
; Test that the strpbrk folder doesn't simplify a call to the function
|
||||
; declared with an incompatible prototype.
|
||||
;
|
||||
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
|
||||
|
||||
|
@ -7,17 +8,17 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
|
|||
@hello = constant [12 x i8] c"hello world\00"
|
||||
@w = constant [2 x i8] c"w\00"
|
||||
|
||||
declare i16* @strpbrk(i8*, i8*)
|
||||
declare i8 @strpbrk(i8*, i8*)
|
||||
|
||||
; Check that 'strpbrk' functions with the wrong prototype aren't simplified.
|
||||
|
||||
define i16* @test_no_simplify1() {
|
||||
define i8 @test_no_simplify1() {
|
||||
; CHECK-LABEL: @test_no_simplify1(
|
||||
%str = getelementptr [12 x i8], [12 x i8]* @hello, i32 0, i32 0
|
||||
%pat = getelementptr [2 x i8], [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
|
||||
%ret = call i8 @strpbrk(i8* %str, i8* %pat)
|
||||
; CHECK-NEXT: %ret = call i8 @strpbrk
|
||||
ret i8 %ret
|
||||
; CHECK-NEXT: ret i8 %ret
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
;
|
||||
; 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"
|
||||
|
||||
@abcba = constant [6 x i8] c"abcba\00"
|
||||
@abc = constant [4 x i8] c"abc\00"
|
||||
@null = constant [1 x i8] zeroinitializer
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
|
||||
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* readonly, i8** nocapture, i32)
|
||||
declare i32 @strtol(i8* %s, i8** %endptr, i32 %base)
|
||||
; CHECK: declare i32 @strtol(i8* readonly, i8** nocapture, i32)
|
||||
|
||||
declare double @strtod(i8* %s, i8** %endptr, i32 %base)
|
||||
; CHECK: declare double @strtod(i8* readonly, i8** nocapture, i32)
|
||||
declare double @strtod(i8* %s, i8** %endptr)
|
||||
; CHECK: declare double @strtod(i8* readonly, i8** nocapture)
|
||||
|
||||
declare float @strtof(i8* %s, i8** %endptr, i32 %base)
|
||||
; CHECK: declare float @strtof(i8* readonly, i8** nocapture, i32)
|
||||
declare float @strtof(i8* %s, i8** %endptr)
|
||||
; CHECK: declare float @strtof(i8* readonly, i8** nocapture)
|
||||
|
||||
declare i64 @strtoul(i8* %s, i8** %endptr, i32 %base)
|
||||
; CHECK: declare i64 @strtoul(i8* readonly, i8** nocapture, i32)
|
||||
|
@ -27,22 +27,22 @@ declare i64 @strtoull(i8* %s, i8** %endptr, i32 %base)
|
|||
|
||||
define void @test_simplify1(i8* %x, i8** %endptr) {
|
||||
; CHECK-LABEL: @test_simplify1(
|
||||
call i64 @strtol(i8* %x, i8** null, i32 10)
|
||||
; CHECK-NEXT: call i64 @strtol(i8* nocapture %x, i8** null, i32 10)
|
||||
call i32 @strtol(i8* %x, i8** null, i32 10)
|
||||
; CHECK-NEXT: call i32 @strtol(i8* nocapture %x, i8** null, i32 10)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_simplify2(i8* %x, i8** %endptr) {
|
||||
; CHECK-LABEL: @test_simplify2(
|
||||
call double @strtod(i8* %x, i8** null, i32 10)
|
||||
; CHECK-NEXT: call double @strtod(i8* nocapture %x, i8** null, i32 10)
|
||||
call double @strtod(i8* %x, i8** null)
|
||||
; CHECK-NEXT: call double @strtod(i8* nocapture %x, i8** null)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_simplify3(i8* %x, i8** %endptr) {
|
||||
; CHECK-LABEL: @test_simplify3(
|
||||
call float @strtof(i8* %x, i8** null, i32 10)
|
||||
; CHECK-NEXT: call float @strtof(i8* nocapture %x, i8** null, i32 10)
|
||||
call float @strtof(i8* %x, i8** null)
|
||||
; CHECK-NEXT: call float @strtof(i8* nocapture %x, i8** null)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ define void @test_simplify7(i8* %x, i8** %endptr) {
|
|||
|
||||
define void @test_no_simplify1(i8* %x, i8** %endptr) {
|
||||
; CHECK-LABEL: @test_no_simplify1(
|
||||
call i64 @strtol(i8* %x, i8** %endptr, i32 10)
|
||||
; CHECK-NEXT: call i64 @strtol(i8* %x, i8** %endptr, i32 10)
|
||||
call i32 @strtol(i8* %x, i8** %endptr, i32 10)
|
||||
; CHECK-NEXT: call i32 @strtol(i8* %x, i8** %endptr, i32 10)
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -286,15 +286,15 @@ define {i8, i1} @test_smul4_poison(i8 %V) {
|
|||
}
|
||||
|
||||
; Test a non-intrinsic that we know about as a library call.
|
||||
declare float @fabs(float %x)
|
||||
declare float @fabsf(float %x)
|
||||
|
||||
define float @test_fabs_libcall() {
|
||||
; CHECK-LABEL: @test_fabs_libcall(
|
||||
; CHECK-NEXT: [[X:%.*]] = call float @fabs(float -4.200000e+01)
|
||||
; CHECK-NEXT: [[X:%.*]] = call float @fabsf(float -4.200000e+01)
|
||||
; CHECK-NEXT: ret float 4.200000e+01
|
||||
;
|
||||
|
||||
%x = call float @fabs(float -42.0)
|
||||
%x = call float @fabsf(float -42.0)
|
||||
; This is still a real function call, so instsimplify won't nuke it -- other
|
||||
; passes have to do that.
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ define hidden void @dont_unroll_call(i32* nocapture %a, i32* nocapture readonly
|
|||
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[I1]], [[I]]
|
||||
; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_013]]
|
||||
; CHECK-NEXT: store i32 [[MUL]], i32* [[ARRAYIDX2]], align 4
|
||||
; CHECK-NEXT: call void (i8*, ...) @printf(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 [[I_013]], i32 [[MUL]])
|
||||
; CHECK-NEXT: call i32 (i8*, ...) @printf(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 [[I_013]], i32 [[MUL]])
|
||||
; CHECK-NEXT: [[INC]] = add nuw i32 [[I_013]], 1
|
||||
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[N]]
|
||||
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]]
|
||||
|
@ -224,7 +224,7 @@ for.body: ; preds = %for.body, %entry
|
|||
%mul = mul nsw i32 %i1, %i
|
||||
%arrayidx2 = getelementptr inbounds i32, i32* %a, i32 %i.013
|
||||
store i32 %mul, i32* %arrayidx2, align 4
|
||||
call void (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 %i.013, i32 %mul)
|
||||
call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 %i.013, i32 %mul)
|
||||
%inc = add nuw i32 %i.013, 1
|
||||
%exitcond.not = icmp eq i32 %inc, %N
|
||||
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
|
||||
|
@ -300,4 +300,4 @@ attributes #0 = { optsize }
|
|||
attributes #1 = { minsize }
|
||||
|
||||
@.str = private unnamed_addr constant [12 x i8] c"a[%d] = %d\0A\00", align 1
|
||||
declare void @printf(i8* nocapture readonly, ...)
|
||||
declare i32 @printf(i8* nocapture readonly, ...)
|
||||
|
|
|
@ -56,7 +56,7 @@ exit:
|
|||
|
||||
|
||||
; Similar to the test case above, but checks getVectorCallCost as well.
|
||||
declare float @pow(float, float) readnone nounwind
|
||||
declare float @powf(float, float) readnone nounwind
|
||||
|
||||
; CM: LV: Found uniform instruction: %a = extractvalue { float, float } %sv, 0
|
||||
; CM: LV: Found uniform instruction: %b = extractvalue { float, float } %sv, 1
|
||||
|
@ -94,7 +94,7 @@ loop.body:
|
|||
%a = extractvalue { float, float } %sv, 0
|
||||
%b = extractvalue { float, float } %sv, 1
|
||||
%addr = getelementptr float, float* %dst, i32 %iv
|
||||
%p = call float @pow(float %a, float %b)
|
||||
%p = call float @powf(float %a, float %b)
|
||||
store float %p, float* %addr
|
||||
%iv.next = add nsw i32 %iv, 1
|
||||
%cond = icmp ne i32 %iv.next, 0
|
||||
|
|
|
@ -322,8 +322,8 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
|
|||
"declare i8* @strtok(i8*, i8*)\n"
|
||||
"declare i8* @strtok_r(i8*, i8*, i8**)\n"
|
||||
"declare i64 @strtol(i8*, i8**, i32)\n"
|
||||
"declare i64 @strlcat(i8*, i8**, i64)\n"
|
||||
"declare i64 @strlcpy(i8*, i8**, i64)\n"
|
||||
"declare i64 @strlcat(i8*, i8*, i64)\n"
|
||||
"declare i64 @strlcpy(i8*, i8*, i64)\n"
|
||||
"declare x86_fp80 @strtold(i8*, i8**)\n"
|
||||
"declare i64 @strtoll(i8*, i8**, i32)\n"
|
||||
"declare i64 @strtoul(i8*, i8**, i32)\n"
|
||||
|
@ -482,7 +482,7 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
|
|||
"declare i8* @__stpncpy_chk(i8*, i8*, i64, i64)\n"
|
||||
"declare i8* @__strcpy_chk(i8*, i8*, i64)\n"
|
||||
"declare i8* @__strncpy_chk(i8*, i8*, i64, i64)\n"
|
||||
"declare i8* @__memccpy_chk(i8*, i8*, i32, i64)\n"
|
||||
"declare i8* @__memccpy_chk(i8*, i8*, i32, i64, i64)\n"
|
||||
"declare i8* @__mempcpy_chk(i8*, i8*, i64, i64)\n"
|
||||
"declare i32 @__snprintf_chk(i8*, i64, i32, i64, i8*, ...)\n"
|
||||
"declare i32 @__sprintf_chk(i8*, i32, i64, i8*, ...)\n"
|
||||
|
|
Loading…
Reference in New Issue