140 lines
9.0 KiB
LLVM
140 lines
9.0 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
;
|
|
; Verify that snprintf calls with a constant size not exceeding INT_MAX
|
|
; and a "%s" format string and a const string argument are transformed
|
|
; into memcpy. Also verify that a size in excess of INT_MAX prevents
|
|
; the transformation.
|
|
;
|
|
; RUN: opt < %s -passes=instcombine -S -data-layout="E" | FileCheck %s -check-prefixes=ANY,BE
|
|
; RUN: opt < %s -passes=instcombine -S -data-layout="e" | FileCheck %s -check-prefixes=ANY,LE
|
|
|
|
@pcnt_s = constant [3 x i8] c"%s\00"
|
|
@s = constant [4 x i8] c"123\00"
|
|
|
|
@adst = external global [0 x i8*]
|
|
@asiz = external global [0 x i32]
|
|
|
|
declare i32 @snprintf(i8*, i64, i8*, ...)
|
|
|
|
|
|
; Verify that all snprintf calls with a bound between INT_MAX and down
|
|
; to 0 are transformed to memcpy.
|
|
|
|
define void @fold_snprintf_pcnt_s() {
|
|
; BE-LABEL: @fold_snprintf_pcnt_s(
|
|
; BE-NEXT: [[PDIMAX1:%.*]] = load i32*, i32** bitcast (i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 2147483647) to i32**), align 8
|
|
; BE-NEXT: store i32 825373440, i32* [[PDIMAX1]], align 1
|
|
; BE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 0), align 4
|
|
; BE-NEXT: [[PD52:%.*]] = load i32*, i32** bitcast (i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 5) to i32**), align 8
|
|
; BE-NEXT: store i32 825373440, i32* [[PD52]], align 1
|
|
; BE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 5), align 4
|
|
; BE-NEXT: [[PD43:%.*]] = load i32*, i32** bitcast (i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 4) to i32**), align 8
|
|
; BE-NEXT: store i32 825373440, i32* [[PD43]], align 1
|
|
; BE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 4), align 4
|
|
; BE-NEXT: [[PD3:%.*]] = load i8*, i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 3), align 8
|
|
; BE-NEXT: [[TMP1:%.*]] = bitcast i8* [[PD3]] to i16*
|
|
; BE-NEXT: store i16 12594, i16* [[TMP1]], align 1
|
|
; BE-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds i8, i8* [[PD3]], i64 2
|
|
; BE-NEXT: store i8 0, i8* [[ENDPTR]], align 1
|
|
; BE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 3), align 4
|
|
; BE-NEXT: [[PD2:%.*]] = load i8*, i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 2), align 8
|
|
; BE-NEXT: store i8 49, i8* [[PD2]], align 1
|
|
; BE-NEXT: [[ENDPTR4:%.*]] = getelementptr inbounds i8, i8* [[PD2]], i64 1
|
|
; BE-NEXT: store i8 0, i8* [[ENDPTR4]], align 1
|
|
; BE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 2), align 4
|
|
; BE-NEXT: [[PD1:%.*]] = load i8*, i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 1), align 8
|
|
; BE-NEXT: store i8 0, i8* [[PD1]], align 1
|
|
; BE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 1), align 4
|
|
; BE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 0), align 4
|
|
; BE-NEXT: ret void
|
|
;
|
|
; LE-LABEL: @fold_snprintf_pcnt_s(
|
|
; LE-NEXT: [[PDIMAX1:%.*]] = load i32*, i32** bitcast (i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 2147483647) to i32**), align 8
|
|
; LE-NEXT: store i32 3355185, i32* [[PDIMAX1]], align 1
|
|
; LE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 0), align 4
|
|
; LE-NEXT: [[PD52:%.*]] = load i32*, i32** bitcast (i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 5) to i32**), align 8
|
|
; LE-NEXT: store i32 3355185, i32* [[PD52]], align 1
|
|
; LE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 5), align 4
|
|
; LE-NEXT: [[PD43:%.*]] = load i32*, i32** bitcast (i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 4) to i32**), align 8
|
|
; LE-NEXT: store i32 3355185, i32* [[PD43]], align 1
|
|
; LE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 4), align 4
|
|
; LE-NEXT: [[PD3:%.*]] = load i8*, i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 3), align 8
|
|
; LE-NEXT: [[TMP1:%.*]] = bitcast i8* [[PD3]] to i16*
|
|
; LE-NEXT: store i16 12849, i16* [[TMP1]], align 1
|
|
; LE-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds i8, i8* [[PD3]], i64 2
|
|
; LE-NEXT: store i8 0, i8* [[ENDPTR]], align 1
|
|
; LE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 3), align 4
|
|
; LE-NEXT: [[PD2:%.*]] = load i8*, i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 2), align 8
|
|
; LE-NEXT: store i8 49, i8* [[PD2]], align 1
|
|
; LE-NEXT: [[ENDPTR4:%.*]] = getelementptr inbounds i8, i8* [[PD2]], i64 1
|
|
; LE-NEXT: store i8 0, i8* [[ENDPTR4]], align 1
|
|
; LE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 2), align 4
|
|
; LE-NEXT: [[PD1:%.*]] = load i8*, i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 1), align 8
|
|
; LE-NEXT: store i8 0, i8* [[PD1]], align 1
|
|
; LE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 1), align 4
|
|
; LE-NEXT: store i32 3, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 0), align 4
|
|
; LE-NEXT: ret void
|
|
;
|
|
%fmt = getelementptr [3 x i8], [3 x i8]* @pcnt_s, i32 0, i32 0
|
|
%ps = getelementptr [4 x i8], [4 x i8]* @s, i32 0, i32 0
|
|
|
|
%pdimax = load i8*, i8** getelementptr ([0 x i8*], [0 x i8*]* @adst, i32 0, i32 2147483647)
|
|
%nimax = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %pdimax, i64 2147483647, i8* %fmt, i8* %ps)
|
|
store i32 %nimax, i32* getelementptr ([0 x i32], [0 x i32]* @asiz, i32 0, i32 0)
|
|
|
|
%pd5 = load i8*, i8** getelementptr ([0 x i8*], [0 x i8*]* @adst, i32 0, i32 5)
|
|
%n5 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %pd5, i64 5, i8* %fmt, i8* %ps)
|
|
store i32 %n5, i32* getelementptr ([0 x i32], [0 x i32]* @asiz, i32 0, i32 5)
|
|
|
|
%pd4 = load i8*, i8** getelementptr ([0 x i8*], [0 x i8*]* @adst, i32 0, i32 4)
|
|
%n4 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %pd4, i64 4, i8* %fmt, i8* %ps)
|
|
store i32 %n4, i32* getelementptr ([0 x i32], [0 x i32]* @asiz, i32 0, i32 4)
|
|
|
|
%pd3 = load i8*, i8** getelementptr ([0 x i8*], [0 x i8*]* @adst, i32 0, i32 3)
|
|
%n3 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %pd3, i64 3, i8* %fmt, i8* %ps)
|
|
store i32 %n3, i32* getelementptr ([0 x i32], [0 x i32]* @asiz, i32 0, i32 3)
|
|
|
|
%pd2 = load i8*, i8** getelementptr ([0 x i8*], [0 x i8*]* @adst, i32 0, i32 2)
|
|
%n2 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %pd2, i64 2, i8* %fmt, i8* %ps)
|
|
store i32 %n2, i32* getelementptr ([0 x i32], [0 x i32]* @asiz, i32 0, i32 2)
|
|
|
|
%pd1 = load i8*, i8** getelementptr ([0 x i8*], [0 x i8*]* @adst, i32 0, i32 1)
|
|
%n1 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %pd1, i64 1, i8* %fmt, i8* %ps)
|
|
store i32 %n1, i32* getelementptr ([0 x i32], [0 x i32]* @asiz, i32 0, i32 1)
|
|
|
|
%pd0 = load i8*, i8** getelementptr ([0 x i8*], [0 x i8*]* @adst, i32 0, i32 0)
|
|
%n0 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %pd0, i64 0, i8* %fmt, i8* %ps)
|
|
store i32 %n0, i32* getelementptr ([0 x i32], [0 x i32]* @asiz, i32 0, i32 0)
|
|
|
|
ret void
|
|
}
|
|
|
|
|
|
; Verify that snprintf calls with a bound greater than INT_MAX are not
|
|
; transformed. POSIX requires implementations to set errno to EOVERFLOW
|
|
; so such calls could be folded to just that followed by returning -1.
|
|
|
|
define void @call_snprintf_pcnt_s_ximax() {
|
|
; ANY-LABEL: @call_snprintf_pcnt_s_ximax(
|
|
; ANY-NEXT: [[PDM1:%.*]] = load i8*, i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 1), align 8
|
|
; ANY-NEXT: [[NM1:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* noundef nonnull dereferenceable(1) [[PDM1]], i64 -1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @s, i64 0, i64 0))
|
|
; ANY-NEXT: store i32 [[NM1]], i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 1), align 4
|
|
; ANY-NEXT: [[PDIMAXP1:%.*]] = load i8*, i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @adst, i64 0, i64 0), align 8
|
|
; ANY-NEXT: [[NIMAXP1:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* noundef nonnull dereferenceable(1) [[PDIMAXP1]], i64 2147483648, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @s, i64 0, i64 0))
|
|
; ANY-NEXT: store i32 [[NIMAXP1]], i32* getelementptr inbounds ([0 x i32], [0 x i32]* @asiz, i64 0, i64 0), align 4
|
|
; ANY-NEXT: ret void
|
|
;
|
|
%fmt = getelementptr [3 x i8], [3 x i8]* @pcnt_s, i32 0, i32 0
|
|
%ps = getelementptr [4 x i8], [4 x i8]* @s, i32 0, i32 0
|
|
|
|
%pdm1 = load i8*, i8** getelementptr ([0 x i8*], [0 x i8*]* @adst, i32 0, i32 1)
|
|
%nm1 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %pdm1, i64 -1, i8* %fmt, i8* %ps)
|
|
store i32 %nm1, i32* getelementptr ([0 x i32], [0 x i32]* @asiz, i32 0, i32 1)
|
|
|
|
%pdimaxp1 = load i8*, i8** getelementptr ([0 x i8*], [0 x i8*]* @adst, i32 0, i32 0)
|
|
%nimaxp1 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %pdimaxp1, i64 2147483648, i8* %fmt, i8* %ps)
|
|
store i32 %nimaxp1, i32* getelementptr ([0 x i32], [0 x i32]* @asiz, i32 0, i32 0)
|
|
|
|
ret void
|
|
}
|