Skip to content

Commit

Permalink
[TLI] Check that malloc argument has type size_t
Browse files Browse the repository at this point in the history
DSE assumes that this is the case when forming a calloc from a
malloc + memset pair.

For tests, either update the malloc signature or change the
data layout.
  • Loading branch information
nikic committed Mar 14, 2022
1 parent de5022c commit 04b717c
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 17 deletions.
4 changes: 3 additions & 1 deletion llvm/lib/Analysis/TargetLibraryInfo.cpp
Expand Up @@ -1110,9 +1110,11 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
case LibFunc_system:
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy());
case LibFunc___kmpc_alloc_shared:
return NumParams == 1 && FTy.getReturnType()->isPointerTy();
case LibFunc_malloc:
case LibFunc_vec_malloc:
return (NumParams == 1 && FTy.getReturnType()->isPointerTy());
return NumParams == 1 && FTy.getParamType(0)->isIntegerTy(SizeTBits) &&
FTy.getReturnType()->isPointerTy();
case LibFunc_memcmp:
return NumParams == 3 && FTy.getReturnType()->isIntegerTy(32) &&
FTy.getParamType(0)->isPointerTy() &&
Expand Down
8 changes: 5 additions & 3 deletions llvm/test/Analysis/GlobalsModRef/indirect-global.ll
Expand Up @@ -5,13 +5,15 @@
; Note that this test relies on an unsafe feature of GlobalsModRef. While this
; test is correct and safe, GMR's technique for handling this isn't generally.

target datalayout = "p:32:32:32"

@G = internal global i32* null ; <i32**> [#uses=3]

declare noalias i8* @malloc(i32)
define void @malloc_init() {
; CHECK-LABEL: @malloc_init(
; CHECK-NEXT: [[A:%.*]] = call dereferenceable_or_null(4) i8* @malloc(i32 4)
; CHECK-NEXT: store i8* [[A]], i8** bitcast (i32** @G to i8**), align 8
; CHECK-NEXT: store i8* [[A]], i8** bitcast (i32** @G to i8**), align 4
; CHECK-NEXT: ret void
;
%a = call i8* @malloc(i32 4)
Expand Down Expand Up @@ -40,7 +42,7 @@ declare noalias i8* @calloc(i32, i32)
define void @calloc_init() {
; CHECK-LABEL: @calloc_init(
; CHECK-NEXT: [[A:%.*]] = call dereferenceable_or_null(4) i8* @calloc(i32 4, i32 1)
; CHECK-NEXT: store i8* [[A]], i8** bitcast (i32** @G2 to i8**), align 8
; CHECK-NEXT: store i8* [[A]], i8** bitcast (i32** @G2 to i8**), align 4
; CHECK-NEXT: ret void
;
%a = call i8* @calloc(i32 4, i32 1)
Expand Down Expand Up @@ -69,7 +71,7 @@ declare noalias i8* @my_alloc(i32)
define void @my_alloc_init() {
; CHECK-LABEL: @my_alloc_init(
; CHECK-NEXT: [[A:%.*]] = call i8* @my_alloc(i32 4)
; CHECK-NEXT: store i8* [[A]], i8** bitcast (i32** @G3 to i8**), align 8
; CHECK-NEXT: store i8* [[A]], i8** bitcast (i32** @G3 to i8**), align 4
; CHECK-NEXT: ret void
;
%a = call i8* @my_alloc(i32 4)
Expand Down
12 changes: 6 additions & 6 deletions llvm/test/Transforms/DeadStoreElimination/simple.ll
Expand Up @@ -209,13 +209,13 @@ define void @test_matrix_store(i64 %stride) {
declare void @may_unwind()
define i32* @test_malloc_no_escape_before_return() {
; CHECK-LABEL: @test_malloc_no_escape_before_return(
; CHECK-NEXT: [[PTR:%.*]] = tail call i8* @malloc(i32 4)
; CHECK-NEXT: [[PTR:%.*]] = tail call i8* @malloc(i64 4)
; CHECK-NEXT: [[P:%.*]] = bitcast i8* [[PTR]] to i32*
; CHECK-NEXT: call void @may_unwind()
; CHECK-NEXT: store i32 0, i32* [[P]], align 4
; CHECK-NEXT: ret i32* [[P]]
;
%ptr = tail call i8* @malloc(i32 4)
%ptr = tail call i8* @malloc(i64 4)
%P = bitcast i8* %ptr to i32*
%DEAD = load i32, i32* %P
%DEAD2 = add i32 %DEAD, 1
Expand Down Expand Up @@ -245,14 +245,14 @@ define i32* @test_custom_malloc_no_escape_before_return() {

define i32 addrspace(1)* @test13_addrspacecast() {
; CHECK-LABEL: @test13_addrspacecast(
; CHECK-NEXT: [[P:%.*]] = tail call i8* @malloc(i32 4)
; CHECK-NEXT: [[P:%.*]] = tail call i8* @malloc(i64 4)
; CHECK-NEXT: [[P_BC:%.*]] = bitcast i8* [[P]] to i32*
; CHECK-NEXT: [[P:%.*]] = addrspacecast i32* [[P_BC]] to i32 addrspace(1)*
; CHECK-NEXT: call void @may_unwind()
; CHECK-NEXT: store i32 0, i32 addrspace(1)* [[P]], align 4
; CHECK-NEXT: ret i32 addrspace(1)* [[P]]
;
%p = tail call i8* @malloc(i32 4)
%p = tail call i8* @malloc(i64 4)
%p.bc = bitcast i8* %p to i32*
%P = addrspacecast i32* %p.bc to i32 addrspace(1)*
%DEAD = load i32, i32 addrspace(1)* %P
Expand All @@ -264,7 +264,7 @@ define i32 addrspace(1)* @test13_addrspacecast() {
}


declare noalias i8* @malloc(i32) willreturn
declare noalias i8* @malloc(i64) willreturn
declare noalias i8* @custom_malloc(i32) willreturn
declare noalias i8* @calloc(i32, i32) willreturn

Expand Down Expand Up @@ -302,7 +302,7 @@ define void @malloc_no_escape() {
; CHECK-LABEL: @malloc_no_escape(
; CHECK-NEXT: ret void
;
%m = call i8* @malloc(i32 24)
%m = call i8* @malloc(i64 24)
store i8 0, i8* %m
ret void
}
Expand Down
18 changes: 18 additions & 0 deletions llvm/test/Transforms/DeadStoreElimination/wrong-malloc-size.ll
@@ -0,0 +1,18 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -dse < %s | FileCheck %s

; malloc should have i64 argument under default data layout
declare noalias i8* @malloc(i32)

define i8* @malloc_and_memset_intrinsic(i32 %n) {
; CHECK-LABEL: @malloc_and_memset_intrinsic(
; CHECK-NEXT: [[CALL:%.*]] = call i8* @malloc(i32 [[N:%.*]])
; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 1 [[CALL]], i8 0, i32 [[N]], i1 false)
; CHECK-NEXT: ret i8* [[CALL]]
;
%call = call i8* @malloc(i32 %n)
call void @llvm.memset.p0i8.i32(i8* align 1 %call, i8 0, i32 %n, i1 false)
ret i8* %call
}

declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1 immarg) #2
5 changes: 4 additions & 1 deletion llvm/test/Transforms/InstCombine/malloc-free.ll
@@ -1,6 +1,9 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
; PR1201

target datalayout = "p:32:32:32"

define i32 @main(i32 %argc, i8** %argv) {
; CHECK-LABEL: @main(
; CHECK-NEXT: ret i32 0
Expand Down Expand Up @@ -85,7 +88,7 @@ define void @test5(i8* %ptr, i8** %esc) {
; CHECK-NEXT: [[G:%.*]] = call dereferenceable_or_null(700) i8* @malloc(i32 700)
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noundef nonnull align 1 dereferenceable(32) [[PTR:%.*]], i8* noundef nonnull align 1 dereferenceable(32) [[A]], i32 32, i1 false)
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i32(i8* noundef nonnull align 1 dereferenceable(32) [[PTR]], i8* noundef nonnull align 1 dereferenceable(32) [[B]], i32 32, i1 false)
; CHECK-NEXT: store i8* [[C]], i8** [[ESC:%.*]], align 8
; CHECK-NEXT: store i8* [[C]], i8** [[ESC:%.*]], align 4
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[D]], i8* [[PTR]], i32 32, i1 true)
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i32(i8* [[E]], i8* [[PTR]], i32 32, i1 true)
; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* [[F]], i8 5, i32 32, i1 true)
Expand Down
6 changes: 3 additions & 3 deletions llvm/test/Transforms/InstCombine/objsize-64.ll
Expand Up @@ -2,19 +2,19 @@
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"

declare noalias i8* @malloc(i32) nounwind
declare noalias i8* @malloc(i64) nounwind
declare noalias nonnull i8* @_Znwm(i64) ; new(unsigned long)
declare i32 @__gxx_personality_v0(...)
declare void @__cxa_call_unexpected(i8*)
declare i64 @llvm.objectsize.i64(i8*, i1) nounwind readonly

define i64 @f1(i8 **%esc) {
; CHECK-LABEL: @f1(
; CHECK-NEXT: [[CALL:%.*]] = call dereferenceable_or_null(4) i8* @malloc(i32 4)
; CHECK-NEXT: [[CALL:%.*]] = call dereferenceable_or_null(4) i8* @malloc(i64 4)
; CHECK-NEXT: store i8* [[CALL]], i8** [[ESC:%.*]], align 8
; CHECK-NEXT: ret i64 4
;
%call = call i8* @malloc(i32 4)
%call = call i8* @malloc(i64 4)
store i8* %call, i8** %esc
%size = call i64 @llvm.objectsize.i64(i8* %call, i1 false)
ret i64 %size
Expand Down
6 changes: 3 additions & 3 deletions llvm/test/Transforms/MetaRenamer/metarenamer.ll
Expand Up @@ -97,17 +97,17 @@ define i32 @varargs_func_6_xxx(i32 %arg_1_xxx, i32 %arg_2_xxx, ...) nounwind uwt
ret i32 6
}

declare noalias i8* @malloc(i32)
declare noalias i8* @malloc(i64)
declare void @free(i8* nocapture)

define void @dont_rename_lib_funcs() {
; CHECK-LABEL: @foo(
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = call i8* @malloc(i32 23)
; CHECK-NEXT: [[TMP:%.*]] = call i8* @malloc(i64 23)
; CHECK-NEXT: call void @free(i8* [[TMP]])
; CHECK-NEXT: ret void
;
%x = call i8* @malloc(i32 23)
%x = call i8* @malloc(i64 23)
call void @free(i8* %x)
ret void
}

0 comments on commit 04b717c

Please sign in to comment.