1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-02-01 05:01:59 +01:00
Nikita Popov f73282e3d5 [InstCombine] Simplify calls with "returned" attribute
If a call argument has the "returned" attribute, we can simplify
the call to the value of that argument. This was already partially
handled by InstSimplify/InstCombine for the case where the argument
is an integer constant, and the result is thus known via known bits.
The non-constant (or non-int) argument cases weren't handled though.

This previously landed as an InstSimplify transform, but was reverted
due to assertion failures when compiling the Linux kernel. The reason
is that simplifying a call to another call breaks assumptions in
call graph updating during inlining. As the code is not easy to fix,
and there is no particularly strong motivation for having this in
InstSimplify, the transform is only performed in InstCombine instead.

Differential Revision: https://reviews.llvm.org/D75815
2020-03-20 10:23:39 +01:00

112 lines
5.4 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; Test lib call simplification of __strcpy_chk calls with various values
; for src, dst, and slen.
;
; RUN: opt < %s -instcombine -S | FileCheck %s
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
@a = common global [60 x i8] zeroinitializer, align 1
@b = common global [60 x i8] zeroinitializer, align 1
@.str = private constant [12 x i8] c"abcdefghijk\00"
; Check cases where slen >= strlen (src).
define i8* @test_simplify1() {
; CHECK-LABEL: @test_simplify1(
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
%src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0
%ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 60)
ret i8* %ret
}
define i8* @test_simplify2() {
; CHECK-LABEL: @test_simplify2(
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
%src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0
%ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 12)
ret i8* %ret
}
define i8* @test_simplify3() {
; CHECK-LABEL: @test_simplify3(
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
%src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0
%ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 -1)
ret i8* %ret
}
; Check cases where there are no string constants.
define i8* @test_simplify4() {
; CHECK-LABEL: @test_simplify4(
; CHECK-NEXT: [[STRCPY:%.*]] = call i8* @strcpy(i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0))
; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
%src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0
%ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 -1)
ret i8* %ret
}
; Check case where the string length is not constant.
define i8* @test_simplify5() {
; CHECK-LABEL: @test_simplify5(
; CHECK-NEXT: [[LEN:%.*]] = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false)
; CHECK-NEXT: [[TMP1:%.*]] = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 [[LEN]])
; CHECK-NEXT: ret i8* [[TMP1]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
%src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0
%len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false, i1 false)
%ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 %len)
ret i8* %ret
}
; Check case where the source and destination are the same.
define i8* @test_simplify6() {
; CHECK-LABEL: @test_simplify6(
; CHECK-NEXT: [[LEN:%.*]] = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false)
; CHECK-NEXT: [[RET:%.*]] = call i8* @__strcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i32 [[LEN]])
; CHECK-NEXT: ret i8* [[RET]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
%len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false, i1 false)
%ret = call i8* @__strcpy_chk(i8* %dst, i8* %dst, i32 %len)
ret i8* %ret
}
; Check case where slen < strlen (src).
define i8* @test_no_simplify1() {
; CHECK-LABEL: @test_no_simplify1(
; CHECK-NEXT: [[RET:%.*]] = call i8* @__strcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 8)
; CHECK-NEXT: ret i8* [[RET]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
%src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0
%ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 8)
ret i8* %ret
}
declare i8* @__strcpy_chk(i8*, i8*, i32) nounwind
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1, i1) nounwind readonly