If nonnull is already set, we currently skip setting both nonnull and dereferenceable. Make these independent, to avoid regressions when additional nonnull attributes are inferred earlier.
175 lines
5.5 KiB
LLVM
175 lines
5.5 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; Test that the printf library call simplifier works correctly.
|
|
;
|
|
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
|
|
; RUN: opt < %s -mtriple xcore-xmos-elf -passes=instcombine -S | FileCheck %s -check-prefix=CHECK-IPRINTF
|
|
|
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
|
|
|
@hello_world = constant [13 x i8] c"hello world\0A\00"
|
|
@h = constant [2 x i8] c"h\00"
|
|
@h2 = constant [3 x i8] c"%%\00"
|
|
@percent = constant [2 x i8] c"%\00"
|
|
@percent_c = constant [3 x i8] c"%c\00"
|
|
@percent_d = constant [3 x i8] c"%d\00"
|
|
@percent_f = constant [3 x i8] c"%f\00"
|
|
@percent_s = constant [4 x i8] c"%s\0A\00"
|
|
@empty = constant [1 x i8] c"\00"
|
|
|
|
declare i32 @printf(ptr, ...)
|
|
|
|
; Check printf("") -> noop.
|
|
|
|
define void @test_simplify1() {
|
|
; CHECK-LABEL: @test_simplify1(
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
; CHECK-IPRINTF-LABEL: @test_simplify1(
|
|
; CHECK-IPRINTF-NEXT: ret void
|
|
;
|
|
call i32 (ptr, ...) @printf(ptr @empty)
|
|
ret void
|
|
}
|
|
|
|
; Check printf("x") -> putchar('x'), even for '%'.
|
|
|
|
define void @test_simplify2() {
|
|
; CHECK-LABEL: @test_simplify2(
|
|
; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 104)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
; CHECK-IPRINTF-LABEL: @test_simplify2(
|
|
; CHECK-IPRINTF-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 104)
|
|
; CHECK-IPRINTF-NEXT: ret void
|
|
;
|
|
call i32 (ptr, ...) @printf(ptr @h)
|
|
ret void
|
|
}
|
|
|
|
; Special case: printf("%%") -> putchar('%').
|
|
|
|
define void @test_simplify2b() {
|
|
; CHECK-LABEL: @test_simplify2b(
|
|
; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 37)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
; CHECK-IPRINTF-LABEL: @test_simplify2b(
|
|
; CHECK-IPRINTF-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 37)
|
|
; CHECK-IPRINTF-NEXT: ret void
|
|
;
|
|
call i32 (ptr, ...) @printf(ptr @h2)
|
|
ret void
|
|
}
|
|
|
|
define void @test_simplify3() {
|
|
; CHECK-LABEL: @test_simplify3(
|
|
; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 37)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
; CHECK-IPRINTF-LABEL: @test_simplify3(
|
|
; CHECK-IPRINTF-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 37)
|
|
; CHECK-IPRINTF-NEXT: ret void
|
|
;
|
|
call i32 (ptr, ...) @printf(ptr @percent)
|
|
ret void
|
|
}
|
|
|
|
; Check printf("foo\n") -> puts("foo").
|
|
|
|
define void @test_simplify4() {
|
|
; CHECK-LABEL: @test_simplify4(
|
|
; CHECK-NEXT: [[PUTS:%.*]] = call i32 @puts(ptr nonnull dereferenceable(1) @str)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
; CHECK-IPRINTF-LABEL: @test_simplify4(
|
|
; CHECK-IPRINTF-NEXT: [[PUTS:%.*]] = call i32 @puts(ptr nonnull dereferenceable(1) @str)
|
|
; CHECK-IPRINTF-NEXT: ret void
|
|
;
|
|
call i32 (ptr, ...) @printf(ptr @hello_world)
|
|
ret void
|
|
}
|
|
|
|
; Check printf("%c", chr) -> putchar(chr).
|
|
|
|
define void @test_simplify5() {
|
|
; CHECK-LABEL: @test_simplify5(
|
|
; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 104)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
; CHECK-IPRINTF-LABEL: @test_simplify5(
|
|
; CHECK-IPRINTF-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 104)
|
|
; CHECK-IPRINTF-NEXT: ret void
|
|
;
|
|
call i32 (ptr, ...) @printf(ptr @percent_c, i8 104)
|
|
ret void
|
|
}
|
|
|
|
; Check printf("%s\n", str) -> puts(str).
|
|
|
|
define void @test_simplify6() {
|
|
; CHECK-LABEL: @test_simplify6(
|
|
; CHECK-NEXT: [[PUTS:%.*]] = call i32 @puts(ptr nonnull dereferenceable(1) @hello_world)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
; CHECK-IPRINTF-LABEL: @test_simplify6(
|
|
; CHECK-IPRINTF-NEXT: [[PUTS:%.*]] = call i32 @puts(ptr nonnull dereferenceable(1) @hello_world)
|
|
; CHECK-IPRINTF-NEXT: ret void
|
|
;
|
|
call i32 (ptr, ...) @printf(ptr @percent_s, ptr @hello_world)
|
|
ret void
|
|
}
|
|
|
|
; Check printf(format, ...) -> iprintf(format, ...) if no floating point.
|
|
|
|
define void @test_simplify7() {
|
|
; CHECK-LABEL: @test_simplify7(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @percent_d, i32 187)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
; CHECK-IPRINTF-LABEL: @test_simplify7(
|
|
; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (ptr, ...) @iprintf(ptr nonnull @percent_d, i32 187)
|
|
; CHECK-IPRINTF-NEXT: ret void
|
|
;
|
|
call i32 (ptr, ...) @printf(ptr @percent_d, i32 187)
|
|
ret void
|
|
}
|
|
|
|
define void @test_no_simplify1() {
|
|
; CHECK-LABEL: @test_no_simplify1(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @percent_f, double 1.870000e+00)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
; CHECK-IPRINTF-LABEL: @test_no_simplify1(
|
|
; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @percent_f, double 1.870000e+00)
|
|
; CHECK-IPRINTF-NEXT: ret void
|
|
;
|
|
call i32 (ptr, ...) @printf(ptr @percent_f, double 1.87)
|
|
ret void
|
|
}
|
|
|
|
define void @test_no_simplify2(ptr %fmt, double %d) {
|
|
; CHECK-LABEL: @test_no_simplify2(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) [[FMT:%.*]], double [[D:%.*]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
; CHECK-IPRINTF-LABEL: @test_no_simplify2(
|
|
; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) [[FMT:%.*]], double [[D:%.*]])
|
|
; CHECK-IPRINTF-NEXT: ret void
|
|
;
|
|
call i32 (ptr, ...) @printf(ptr %fmt, double %d)
|
|
ret void
|
|
}
|
|
|
|
define i32 @test_no_simplify3() {
|
|
; CHECK-LABEL: @test_no_simplify3(
|
|
; CHECK-NEXT: [[RET:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @h)
|
|
; CHECK-NEXT: ret i32 [[RET]]
|
|
;
|
|
; CHECK-IPRINTF-LABEL: @test_no_simplify3(
|
|
; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (ptr, ...) @iprintf(ptr nonnull @h)
|
|
; CHECK-IPRINTF-NEXT: ret i32 [[TMP1]]
|
|
;
|
|
%ret = call i32 (ptr, ...) @printf(ptr @h)
|
|
ret i32 %ret
|
|
}
|