diff options
Diffstat (limited to 'test/Transforms')
480 files changed, 17951 insertions, 2829 deletions
diff --git a/test/Transforms/AddDiscriminators/basic.ll b/test/Transforms/AddDiscriminators/basic.ll index b12cbee6adb5..7c8b3d3a7ce8 100644 --- a/test/Transforms/AddDiscriminators/basic.ll +++ b/test/Transforms/AddDiscriminators/basic.ll @@ -40,20 +40,20 @@ attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointe !llvm.module.flags = !{!7, !8} !llvm.ident = !{!9} -!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [basic.c] [DW_LANG_C99] -!1 = metadata !{metadata !"basic.c", metadata !"."} -!2 = metadata !{} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (i32)* @foo, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [basic.c] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!8 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} -!9 = metadata !{metadata !"clang version 3.5 "} -!10 = metadata !{i32 3, i32 0, metadata !11, null} -!11 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 0, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [basic.c] -!12 = metadata !{i32 4, i32 0, metadata !4, null} - -; CHECK: !12 = metadata !{i32 3, i32 0, metadata !13, null} -; CHECK: !13 = metadata !{i32 786443, metadata !1, metadata !11, i32 3, i32 0, i32 1, i32 0} ; [ DW_TAG_lexical_block ] [./basic.c] -; CHECK: !14 = metadata !{i32 4, i32 0, metadata !4, null} +!0 = !{!"0x11\0012\00clang version 3.5 \000\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [basic.c] [DW_LANG_C99] +!1 = !{!"basic.c", !"."} +!2 = !{} +!3 = !{!4} +!4 = !{!"0x2e\00foo\00foo\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, void (i32)* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [basic.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 1, !"Debug Info Version", i32 2} +!9 = !{!"clang version 3.5 "} +!10 = !MDLocation(line: 3, scope: !11) +!11 = !{!"0xb\003\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [basic.c] +!12 = !MDLocation(line: 4, scope: !4) + +; CHECK: !12 = !MDLocation(line: 3, scope: !13) +; CHECK: !13 = !{!"0xb\001", !1, !11} ; [ DW_TAG_lexical_block ] [./basic.c] +; CHECK: !14 = !MDLocation(line: 4, scope: !4) diff --git a/test/Transforms/AddDiscriminators/first-only.ll b/test/Transforms/AddDiscriminators/first-only.ll index f3b0357e5766..153cfc8a44cc 100644 --- a/test/Transforms/AddDiscriminators/first-only.ll +++ b/test/Transforms/AddDiscriminators/first-only.ll @@ -50,33 +50,33 @@ attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointe !llvm.module.flags = !{!7, !8} !llvm.ident = !{!9} -!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 (trunk 199750) (llvm/trunk 199751)", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [first-only.c] [DW_LANG_C99] -!1 = metadata !{metadata !"first-only.c", metadata !"."} -!2 = metadata !{i32 0} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (i32)* @foo, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [first-only.c] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!8 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} -!9 = metadata !{metadata !"clang version 3.5 (trunk 199750) (llvm/trunk 199751)"} -!10 = metadata !{i32 3, i32 0, metadata !11, null} - -!11 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [first-only.c] -; CHECK: !11 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 0, i32 0} - -!12 = metadata !{i32 3, i32 0, metadata !13, null} - -!13 = metadata !{i32 786443, metadata !1, metadata !11, i32 3, i32 0, i32 1} ; [ DW_TAG_lexical_block ] [first-only.c] -; CHECK: !13 = metadata !{i32 786443, metadata !1, metadata !14, i32 3, i32 0, i32 1, i32 0} ; [ DW_TAG_lexical_block ] [./first-only.c] - -!14 = metadata !{i32 4, i32 0, metadata !13, null} -; CHECK: !14 = metadata !{i32 786443, metadata !1, metadata !11, i32 3, i32 0, i32 1} - -!15 = metadata !{i32 5, i32 0, metadata !13, null} -; CHECK: !15 = metadata !{i32 4, i32 0, metadata !14, null} - -!16 = metadata !{i32 6, i32 0, metadata !4, null} -; CHECK: !16 = metadata !{i32 5, i32 0, metadata !14, null} -; CHECK: !17 = metadata !{i32 6, i32 0, metadata !4, null} +!0 = !{!"0x11\0012\00clang version 3.5 (trunk 199750) (llvm/trunk 199751)\000\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [first-only.c] [DW_LANG_C99] +!1 = !{!"first-only.c", !"."} +!2 = !{i32 0} +!3 = !{!4} +!4 = !{!"0x2e\00foo\00foo\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, void (i32)* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [first-only.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 1, !"Debug Info Version", i32 2} +!9 = !{!"clang version 3.5 (trunk 199750) (llvm/trunk 199751)"} +!10 = !MDLocation(line: 3, scope: !11) + +!11 = !{!"0xb\003\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [first-only.c] +; CHECK: !11 = !{!"0xb\003\000\000", !1, !4} + +!12 = !MDLocation(line: 3, scope: !13) + +!13 = !{!"0xb\003\000\001", !1, !11} ; [ DW_TAG_lexical_block ] [first-only.c] +; CHECK: !13 = !{!"0xb\001", !1, !14} ; [ DW_TAG_lexical_block ] [./first-only.c] + +!14 = !MDLocation(line: 4, scope: !13) +; CHECK: !14 = !{!"0xb\003\000\001", !1, !11} + +!15 = !MDLocation(line: 5, scope: !13) +; CHECK: !15 = !MDLocation(line: 4, scope: !14) + +!16 = !MDLocation(line: 6, scope: !4) +; CHECK: !16 = !MDLocation(line: 5, scope: !14) +; CHECK: !17 = !MDLocation(line: 6, scope: !4) diff --git a/test/Transforms/AddDiscriminators/multiple.ll b/test/Transforms/AddDiscriminators/multiple.ll index 0241a0c1a0b1..5e552a87bbb2 100644 --- a/test/Transforms/AddDiscriminators/multiple.ll +++ b/test/Transforms/AddDiscriminators/multiple.ll @@ -51,21 +51,21 @@ attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointe !llvm.module.flags = !{!7, !8} !llvm.ident = !{!9} -!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 (trunk 199750) (llvm/trunk 199751)", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [multiple.c] [DW_LANG_C99] -!1 = metadata !{metadata !"multiple.c", metadata !"."} -!2 = metadata !{i32 0} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (i32)* @foo, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [multiple.c] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!8 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} -!9 = metadata !{metadata !"clang version 3.5 (trunk 199750) (llvm/trunk 199751)"} -!10 = metadata !{i32 3, i32 0, metadata !11, null} -!11 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [multiple.c] -!12 = metadata !{i32 4, i32 0, metadata !4, null} +!0 = !{!"0x11\0012\00clang version 3.5 (trunk 199750) (llvm/trunk 199751)\000\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [multiple.c] [DW_LANG_C99] +!1 = !{!"multiple.c", !"."} +!2 = !{i32 0} +!3 = !{!4} +!4 = !{!"0x2e\00foo\00foo\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, void (i32)* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [multiple.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 1, !"Debug Info Version", i32 2} +!9 = !{!"clang version 3.5 (trunk 199750) (llvm/trunk 199751)"} +!10 = !MDLocation(line: 3, scope: !11) +!11 = !{!"0xb\003\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [multiple.c] +!12 = !MDLocation(line: 4, scope: !4) -; CHECK: !12 = metadata !{i32 3, i32 0, metadata !13, null} -; CHECK: !13 = metadata !{i32 786443, metadata !1, metadata !11, i32 3, i32 0, i32 1, i32 0} ; [ DW_TAG_lexical_block ] [./multiple.c] -; CHECK: !14 = metadata !{i32 3, i32 0, metadata !15, null} -; CHECK: !15 = metadata !{i32 786443, metadata !1, metadata !11, i32 3, i32 0, i32 2, i32 1} ; [ DW_TAG_lexical_block ] [./multiple.c] +; CHECK: !12 = !MDLocation(line: 3, scope: !13) +; CHECK: !13 = !{!"0xb\001", !1, !11} ; [ DW_TAG_lexical_block ] [./multiple.c] +; CHECK: !14 = !MDLocation(line: 3, scope: !15) +; CHECK: !15 = !{!"0xb\002", !1, !11} ; [ DW_TAG_lexical_block ] [./multiple.c] diff --git a/test/Transforms/AddDiscriminators/no-discriminators.ll b/test/Transforms/AddDiscriminators/no-discriminators.ll index f7b45e295551..dd7faf0a71e3 100644 --- a/test/Transforms/AddDiscriminators/no-discriminators.ll +++ b/test/Transforms/AddDiscriminators/no-discriminators.ll @@ -17,7 +17,7 @@ entry: %retval = alloca i32, align 4 %i.addr = alloca i64, align 8 store i64 %i, i64* %i.addr, align 8 - call void @llvm.dbg.declare(metadata !{i64* %i.addr}, metadata !13), !dbg !14 + call void @llvm.dbg.declare(metadata i64* %i.addr, metadata !13, metadata !{}), !dbg !14 %0 = load i64* %i.addr, align 8, !dbg !15 ; CHECK: %0 = load i64* %i.addr, align 8, !dbg !15 %cmp = icmp slt i64 %0, 5, !dbg !15 @@ -39,7 +39,7 @@ return: ; preds = %if.else, %if.then } ; Function Attrs: nounwind readnone -declare void @llvm.dbg.declare(metadata, metadata) #1 +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone } @@ -48,24 +48,24 @@ attributes #1 = { nounwind readnone } !llvm.module.flags = !{!10, !11} !llvm.ident = !{!12} -!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5.0 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 1} ; [ DW_TAG_compile_unit ] [./no-discriminators] [DW_LANG_C99] -!1 = metadata !{metadata !"no-discriminators", metadata !"."} -!2 = metadata !{} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i64)* @foo, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [./no-discriminators] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{metadata !8, metadata !9} -!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] -!9 = metadata !{i32 786468, null, null, metadata !"long int", i32 0, i64 64, i64 64, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [long int] [line 0, size 64, align 64, offset 0, enc DW_ATE_signed] -!10 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} -; CHECK: !10 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} -!11 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} -!12 = metadata !{metadata !"clang version 3.5.0 "} -!13 = metadata !{i32 786689, metadata !4, metadata !"i", metadata !5, i32 16777217, metadata !9, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [i] [line 1] -!14 = metadata !{i32 1, i32 0, metadata !4, null} -!15 = metadata !{i32 2, i32 0, metadata !16, null} -; CHECK: !15 = metadata !{i32 2, i32 0, metadata !16, null} -!16 = metadata !{i32 786443, metadata !1, metadata !4, i32 2, i32 0, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [./no-discriminators] -; CHECK: !16 = metadata !{i32 786443, metadata !1, metadata !4, i32 2, i32 0, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [./no-discriminators] -!17 = metadata !{i32 3, i32 0, metadata !4, null} +!0 = !{!"0x11\0012\00clang version 3.5.0 \000\00\000\00\001", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [./no-discriminators] [DW_LANG_C99] +!1 = !{!"no-discriminators", !"."} +!2 = !{} +!3 = !{!4} +!4 = !{!"0x2e\00foo\00foo\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, i32 (i64)* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [./no-discriminators] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{!8, !9} +!8 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!9 = !{!"0x24\00long int\000\0064\0064\000\000\005", null, null} ; [ DW_TAG_base_type ] [long int] [line 0, size 64, align 64, offset 0, enc DW_ATE_signed] +!10 = !{i32 2, !"Dwarf Version", i32 2} +; CHECK: !10 = !{i32 2, !"Dwarf Version", i32 2} +!11 = !{i32 1, !"Debug Info Version", i32 2} +!12 = !{!"clang version 3.5.0 "} +!13 = !{!"0x101\00i\0016777217\000", !4, !5, !9} ; [ DW_TAG_arg_variable ] [i] [line 1] +!14 = !MDLocation(line: 1, scope: !4) +!15 = !MDLocation(line: 2, scope: !16) +; CHECK: !15 = !MDLocation(line: 2, scope: !16) +!16 = !{!"0xb\002\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [./no-discriminators] +; CHECK: !16 = !{!"0xb\002\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [./no-discriminators] +!17 = !MDLocation(line: 3, scope: !4) diff --git a/test/Transforms/AlignmentFromAssumptions/simple.ll b/test/Transforms/AlignmentFromAssumptions/simple.ll new file mode 100644 index 000000000000..884c8bad02f5 --- /dev/null +++ b/test/Transforms/AlignmentFromAssumptions/simple.ll @@ -0,0 +1,215 @@ +target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" +; RUN: opt < %s -alignment-from-assumptions -S | FileCheck %s + +define i32 @foo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %0 = load i32* %a, align 4 + ret i32 %0 + +; CHECK-LABEL: @foo +; CHECK: load i32* {{[^,]+}}, align 32 +; CHECK: ret i32 +} + +define i32 @foo2(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %offsetptr = add i64 %ptrint, 24 + %maskedptr = and i64 %offsetptr, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %arrayidx = getelementptr inbounds i32* %a, i64 2 + %0 = load i32* %arrayidx, align 4 + ret i32 %0 + +; CHECK-LABEL: @foo2 +; CHECK: load i32* {{[^,]+}}, align 16 +; CHECK: ret i32 +} + +define i32 @foo2a(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %offsetptr = add i64 %ptrint, 28 + %maskedptr = and i64 %offsetptr, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %arrayidx = getelementptr inbounds i32* %a, i64 -1 + %0 = load i32* %arrayidx, align 4 + ret i32 %0 + +; CHECK-LABEL: @foo2a +; CHECK: load i32* {{[^,]+}}, align 32 +; CHECK: ret i32 +} + +define i32 @goo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %0 = load i32* %a, align 4 + ret i32 %0 + +; CHECK-LABEL: @goo +; CHECK: load i32* {{[^,]+}}, align 32 +; CHECK: ret i32 +} + +define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 8 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @hoo +; CHECK: load i32* %arrayidx, align 32 +; CHECK: ret i32 %add.lcssa +} + +define i32 @joo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 4, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 8 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @joo +; CHECK: load i32* %arrayidx, align 16 +; CHECK: ret i32 %add.lcssa +} + +define i32 @koo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 4 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @koo +; CHECK: load i32* %arrayidx, align 16 +; CHECK: ret i32 %add.lcssa +} + +define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ -4, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 4 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @koo2 +; CHECK: load i32* %arrayidx, align 16 +; CHECK: ret i32 %add.lcssa +} + +define i32 @moo(i32* nocapture %a) nounwind uwtable { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %0 = bitcast i32* %a to i8* + tail call void @llvm.memset.p0i8.i64(i8* %0, i8 0, i64 64, i32 4, i1 false) + ret i32 undef + +; CHECK-LABEL: @moo +; CHECK: @llvm.memset.p0i8.i64(i8* %0, i8 0, i64 64, i32 32, i1 false) +; CHECK: ret i32 undef +} + +define i32 @moo2(i32* nocapture %a, i32* nocapture %b) nounwind uwtable { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %ptrint1 = ptrtoint i32* %b to i64 + %maskedptr3 = and i64 %ptrint1, 127 + %maskcond4 = icmp eq i64 %maskedptr3, 0 + tail call void @llvm.assume(i1 %maskcond4) + %0 = bitcast i32* %a to i8* + %1 = bitcast i32* %b to i8* + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %1, i64 64, i32 4, i1 false) + ret i32 undef + +; CHECK-LABEL: @moo2 +; CHECK: @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %1, i64 64, i32 32, i1 false) +; CHECK: ret i32 undef +} + +declare void @llvm.assume(i1) nounwind + +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind + diff --git a/test/Transforms/AlignmentFromAssumptions/simple32.ll b/test/Transforms/AlignmentFromAssumptions/simple32.ll new file mode 100644 index 000000000000..166e7ef38936 --- /dev/null +++ b/test/Transforms/AlignmentFromAssumptions/simple32.ll @@ -0,0 +1,215 @@ +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64" +; RUN: opt < %s -alignment-from-assumptions -S | FileCheck %s + +define i32 @foo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %0 = load i32* %a, align 4 + ret i32 %0 + +; CHECK-LABEL: @foo +; CHECK: load i32* {{[^,]+}}, align 32 +; CHECK: ret i32 +} + +define i32 @foo2(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %offsetptr = add i64 %ptrint, 24 + %maskedptr = and i64 %offsetptr, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %arrayidx = getelementptr inbounds i32* %a, i64 2 + %0 = load i32* %arrayidx, align 4 + ret i32 %0 + +; CHECK-LABEL: @foo2 +; CHECK: load i32* {{[^,]+}}, align 16 +; CHECK: ret i32 +} + +define i32 @foo2a(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %offsetptr = add i64 %ptrint, 28 + %maskedptr = and i64 %offsetptr, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %arrayidx = getelementptr inbounds i32* %a, i64 -1 + %0 = load i32* %arrayidx, align 4 + ret i32 %0 + +; CHECK-LABEL: @foo2a +; CHECK: load i32* {{[^,]+}}, align 32 +; CHECK: ret i32 +} + +define i32 @goo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %0 = load i32* %a, align 4 + ret i32 %0 + +; CHECK-LABEL: @goo +; CHECK: load i32* {{[^,]+}}, align 32 +; CHECK: ret i32 +} + +define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 8 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @hoo +; CHECK: load i32* %arrayidx, align 32 +; CHECK: ret i32 %add.lcssa +} + +define i32 @joo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 4, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 8 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @joo +; CHECK: load i32* %arrayidx, align 16 +; CHECK: ret i32 %add.lcssa +} + +define i32 @koo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 4 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @koo +; CHECK: load i32* %arrayidx, align 16 +; CHECK: ret i32 %add.lcssa +} + +define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ -4, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 4 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @koo2 +; CHECK: load i32* %arrayidx, align 16 +; CHECK: ret i32 %add.lcssa +} + +define i32 @moo(i32* nocapture %a) nounwind uwtable { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %0 = bitcast i32* %a to i8* + tail call void @llvm.memset.p0i8.i64(i8* %0, i8 0, i64 64, i32 4, i1 false) + ret i32 undef + +; CHECK-LABEL: @moo +; CHECK: @llvm.memset.p0i8.i64(i8* %0, i8 0, i64 64, i32 32, i1 false) +; CHECK: ret i32 undef +} + +define i32 @moo2(i32* nocapture %a, i32* nocapture %b) nounwind uwtable { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %ptrint1 = ptrtoint i32* %b to i64 + %maskedptr3 = and i64 %ptrint1, 127 + %maskcond4 = icmp eq i64 %maskedptr3, 0 + tail call void @llvm.assume(i1 %maskcond4) + %0 = bitcast i32* %a to i8* + %1 = bitcast i32* %b to i8* + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %1, i64 64, i32 4, i1 false) + ret i32 undef + +; CHECK-LABEL: @moo2 +; CHECK: @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %1, i64 64, i32 32, i1 false) +; CHECK: ret i32 undef +} + +declare void @llvm.assume(i1) nounwind + +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind + diff --git a/test/Transforms/AlignmentFromAssumptions/start-unk.ll b/test/Transforms/AlignmentFromAssumptions/start-unk.ll new file mode 100644 index 000000000000..b7fe24947cb5 --- /dev/null +++ b/test/Transforms/AlignmentFromAssumptions/start-unk.ll @@ -0,0 +1,154 @@ +; RUN: opt -alignment-from-assumptions -S < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%type1 = type { %type2 } +%type2 = type { [4 x i8] } + +; Function Attrs: nounwind +declare void @llvm.assume(i1) #0 + +; Function Attrs: nounwind readnone +declare i32 @llvm.bswap.i32(i32) #1 + +; Function Attrs: nounwind uwtable +define void @test1() unnamed_addr #2 align 2 { + +; CHECK-LABEL: @test1 + +entry: + br i1 undef, label %if.then, label %if.end + +if.then: ; preds = %entry + unreachable + +if.end: ; preds = %entry + br i1 undef, label %return, label %if.end8 + +if.end8: ; preds = %if.end + br i1 undef, label %if.then13, label %if.end14 + +if.then13: ; preds = %if.end8 + unreachable + +if.end14: ; preds = %if.end8 + br i1 undef, label %cond.false.i129, label %cond.end.i136 + +cond.false.i129: ; preds = %if.end14 + unreachable + +cond.end.i136: ; preds = %if.end14 + br i1 undef, label %land.lhs.true.i, label %if.end.i145 + +land.lhs.true.i: ; preds = %cond.end.i136 + br i1 undef, label %if.end.i145, label %if.then.i137 + +if.then.i137: ; preds = %land.lhs.true.i + br i1 undef, label %cond.false8.i, label %cond.end9.i + +cond.false8.i: ; preds = %if.then.i137 + unreachable + +cond.end9.i: ; preds = %if.then.i137 + br i1 undef, label %if.then23, label %if.end24 + +if.end.i145: ; preds = %land.lhs.true.i, %cond.end.i136 + unreachable + +if.then23: ; preds = %cond.end9.i + unreachable + +if.end24: ; preds = %cond.end9.i + br i1 undef, label %for.end, label %for.body.lr.ph + +for.body.lr.ph: ; preds = %if.end24 + unreachable + +for.end: ; preds = %if.end24 + br i1 undef, label %if.end123, label %if.then121 + +if.then121: ; preds = %for.end + unreachable + +if.end123: ; preds = %for.end + br i1 undef, label %if.end150, label %if.then126 + +if.then126: ; preds = %if.end123 + %ptrint.i.i185 = ptrtoint %type1* undef to i64 + %maskedptr.i.i186 = and i64 %ptrint.i.i185, 1 + %maskcond.i.i187 = icmp eq i64 %maskedptr.i.i186, 0 + tail call void @llvm.assume(i1 %maskcond.i.i187) #0 + %ret.0..sroa_cast.i.i188 = bitcast %type1* undef to i32* + %ret.0.copyload.i.i189 = load i32* %ret.0..sroa_cast.i.i188, align 2 + +; CHECK: load {{.*}} align 2 + + %0 = tail call i32 @llvm.bswap.i32(i32 %ret.0.copyload.i.i189) #0 + %conv131 = zext i32 %0 to i64 + %add.ptr132 = getelementptr inbounds i8* undef, i64 %conv131 + %1 = bitcast i8* %add.ptr132 to %type1* + br i1 undef, label %if.end150, label %if.end.i173 + +if.end.i173: ; preds = %if.then126 + br i1 undef, label %test1.exit, label %cond.false.i.i.i.i174 + +cond.false.i.i.i.i174: ; preds = %if.end.i173 + unreachable + +test1.exit: ; preds = %if.end.i173 + br i1 undef, label %test1a.exit, label %if.end.i124 + +if.end.i124: ; preds = %test1.exit + unreachable + +test1a.exit: ; preds = %test1.exit + br i1 undef, label %if.end150, label %for.body137.lr.ph + +for.body137.lr.ph: ; preds = %test1a.exit + br label %for.body137 + +for.body137: ; preds = %test1b.exit, %for.body137.lr.ph + %ShndxTable.0309 = phi %type1* [ %1, %for.body137.lr.ph ], [ %incdec.ptr, %test1b.exit ] + %ret.0..sroa_cast.i.i106 = bitcast %type1* %ShndxTable.0309 to i32* + br i1 undef, label %for.body137.if.end146_crit_edge, label %if.then140 + +for.body137.if.end146_crit_edge: ; preds = %for.body137 + %incdec.ptr = getelementptr inbounds %type1* %ShndxTable.0309, i64 1 + br i1 undef, label %cond.false.i70, label %cond.end.i + +if.then140: ; preds = %for.body137 + %ret.0.copyload.i.i102 = load i32* %ret.0..sroa_cast.i.i106, align 2 + +; CHECK: load {{.*}} align 2 + + unreachable + +cond.false.i70: ; preds = %for.body137.if.end146_crit_edge + unreachable + +cond.end.i: ; preds = %for.body137.if.end146_crit_edge + br i1 undef, label %test1b.exit, label %cond.false.i.i + +cond.false.i.i: ; preds = %cond.end.i + unreachable + +test1b.exit: ; preds = %cond.end.i + br i1 undef, label %if.end150, label %for.body137 + +if.end150: ; preds = %test1b.exit, %test1a.exit, %if.then126, %if.end123 + br i1 undef, label %for.end176, label %for.body155.lr.ph + +for.body155.lr.ph: ; preds = %if.end150 + unreachable + +for.end176: ; preds = %if.end150 + unreachable + +return: ; preds = %if.end + ret void +} + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } +attributes #2 = { nounwind uwtable } + diff --git a/test/Transforms/ArgumentPromotion/dbg.ll b/test/Transforms/ArgumentPromotion/dbg.ll index 70503afb5870..65cf3678bd99 100644 --- a/test/Transforms/ArgumentPromotion/dbg.ll +++ b/test/Transforms/ArgumentPromotion/dbg.ll @@ -1,22 +1,26 @@ ; RUN: opt < %s -argpromotion -S | FileCheck %s -; CHECK: call void @test(), !dbg [[DBG_LOC:![0-9]]] -; CHECK: [[TEST_FN:.*]] = {{.*}} void ()* @test -; CHECK: [[DBG_LOC]] = metadata !{i32 8, i32 0, metadata [[TEST_FN]], null} +; CHECK: call void @test(i32 % +; CHECK: void (i32)* @test, {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [test] -define internal void @test(i32* %X) { +declare void @sink(i32) + +define internal void @test(i32** %X) { + %1 = load i32** %X, align 8 + %2 = load i32* %1, align 8 + call void @sink(i32 %2) ret void } -define void @caller() { - call void @test(i32* null), !dbg !1 +define void @caller(i32** %Y) { + call void @test(i32** %Y) ret void } !llvm.module.flags = !{!0} !llvm.dbg.cu = !{!3} -!0 = metadata !{i32 2, metadata !"Debug Info Version", i32 1} -!1 = metadata !{i32 8, i32 0, metadata !2, null} -!2 = metadata !{i32 786478, null, null, metadata !"test", metadata !"test", metadata !"", i32 3, null, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (i32*)* @test, null, null, null, i32 3} -!3 = metadata !{i32 786449, null, i32 4, metadata !"clang version 3.5.0 ", i1 false, metadata !"", i32 0, null, null, metadata !4, null, null, metadata !"", i32 2} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/blaikie/dev/scratch/pr20038/reduce/<stdin>] [DW_LANG_C_plus_plus] -!4 = metadata !{metadata !2} +!0 = !{i32 2, !"Debug Info Version", i32 2} +!1 = !MDLocation(line: 8, scope: !2) +!2 = !{!"0x2e\00test\00test\00\003\001\001\000\006\00256\000\003", null, null, null, null, void (i32**)* @test, null, null, null} ; [ DW_TAG_subprogram ] +!3 = !{!"0x11\004\00clang version 3.5.0 \000\00\000\00\002", null, null, null, !4, null, null} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/blaikie/dev/scratch/pr20038/reduce/<stdin>] [DW_LANG_C_plus_plus] +!4 = !{!2} diff --git a/test/Transforms/ArgumentPromotion/fp80.ll b/test/Transforms/ArgumentPromotion/fp80.ll new file mode 100644 index 000000000000..a770d6013d6b --- /dev/null +++ b/test/Transforms/ArgumentPromotion/fp80.ll @@ -0,0 +1,58 @@ +; RUN: opt < %s -argpromotion -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%union.u = type { x86_fp80 } +%struct.s = type { double, i16, i8, [5 x i8] } + +@b = internal global %struct.s { double 3.14, i16 9439, i8 25, [5 x i8] undef }, align 16 + +%struct.Foo = type { i32, i64 } +@a = internal global %struct.Foo { i32 1, i64 2 }, align 8 + +define void @run() { +entry: + tail call i8 @UseLongDoubleUnsafely(%union.u* byval align 16 bitcast (%struct.s* @b to %union.u*)) + tail call x86_fp80 @UseLongDoubleSafely(%union.u* byval align 16 bitcast (%struct.s* @b to %union.u*)) + call i64 @AccessPaddingOfStruct(%struct.Foo* @a) + call i64 @CaptureAStruct(%struct.Foo* @a) + ret void +} + +; CHECK: internal i8 @UseLongDoubleUnsafely(%union.u* byval align 16 %arg) { +define internal i8 @UseLongDoubleUnsafely(%union.u* byval align 16 %arg) { +entry: + %bitcast = bitcast %union.u* %arg to %struct.s* + %gep = getelementptr inbounds %struct.s* %bitcast, i64 0, i32 2 + %result = load i8* %gep + ret i8 %result +} + +; CHECK: internal x86_fp80 @UseLongDoubleSafely(x86_fp80 {{%.*}}) { +define internal x86_fp80 @UseLongDoubleSafely(%union.u* byval align 16 %arg) { + %gep = getelementptr inbounds %union.u* %arg, i64 0, i32 0 + %fp80 = load x86_fp80* %gep + ret x86_fp80 %fp80 +} + +; CHECK: define internal i64 @AccessPaddingOfStruct(%struct.Foo* byval %a) { +define internal i64 @AccessPaddingOfStruct(%struct.Foo* byval %a) { + %p = bitcast %struct.Foo* %a to i64* + %v = load i64* %p + ret i64 %v +} + +; CHECK: define internal i64 @CaptureAStruct(%struct.Foo* byval %a) { +define internal i64 @CaptureAStruct(%struct.Foo* byval %a) { +entry: + %a_ptr = alloca %struct.Foo* + br label %loop + +loop: + %phi = phi %struct.Foo* [ null, %entry ], [ %gep, %loop ] + %0 = phi %struct.Foo* [ %a, %entry ], [ %0, %loop ] + store %struct.Foo* %phi, %struct.Foo** %a_ptr + %gep = getelementptr %struct.Foo* %a, i64 0 + br label %loop +} diff --git a/test/Transforms/ArgumentPromotion/reserve-tbaa.ll b/test/Transforms/ArgumentPromotion/reserve-tbaa.ll index 4688a83f2425..db9d70d337a1 100644 --- a/test/Transforms/ArgumentPromotion/reserve-tbaa.ll +++ b/test/Transforms/ArgumentPromotion/reserve-tbaa.ll @@ -37,16 +37,16 @@ entry: ret i32 0 } -!1 = metadata !{metadata !2, metadata !2, i64 0} -!2 = metadata !{metadata !"long", metadata !3, i64 0} -!3 = metadata !{metadata !"omnipotent char", metadata !4, i64 0} -!4 = metadata !{metadata !"Simple C/C++ TBAA"} -!5 = metadata !{metadata !6, metadata !6, i64 0} -!6 = metadata !{metadata !"int", metadata !3, i64 0} -!7 = metadata !{metadata !3, metadata !3, i64 0} -!8 = metadata !{metadata !9, metadata !9, i64 0} -!9 = metadata !{metadata !"any pointer", metadata !3, i64 0} -; CHECK: ![[I32]] = metadata !{metadata ![[I32_TYPE:[0-9]+]], metadata ![[I32_TYPE]], i64 0} -; CHECK: ![[I32_TYPE]] = metadata !{metadata !"int", metadata !{{.*}}, i64 0} -; CHECK: ![[LONG]] = metadata !{metadata ![[LONG_TYPE:[0-9]+]], metadata ![[LONG_TYPE]], i64 0} -; CHECK: ![[LONG_TYPE]] = metadata !{metadata !"long", metadata !{{.*}}, i64 0} +!1 = !{!2, !2, i64 0} +!2 = !{!"long", !3, i64 0} +!3 = !{!"omnipotent char", !4, i64 0} +!4 = !{!"Simple C/C++ TBAA"} +!5 = !{!6, !6, i64 0} +!6 = !{!"int", !3, i64 0} +!7 = !{!3, !3, i64 0} +!8 = !{!9, !9, i64 0} +!9 = !{!"any pointer", !3, i64 0} +; CHECK: ![[I32]] = !{![[I32_TYPE:[0-9]+]], ![[I32_TYPE]], i64 0} +; CHECK: ![[I32_TYPE]] = !{!"int", !{{.*}}, i64 0} +; CHECK: ![[LONG]] = !{![[LONG_TYPE:[0-9]+]], ![[LONG_TYPE]], i64 0} +; CHECK: ![[LONG_TYPE]] = !{!"long", !{{.*}}, i64 0} diff --git a/test/Transforms/ArgumentPromotion/tail.ll b/test/Transforms/ArgumentPromotion/tail.ll index 43b8996ca18a..2ea387cd2645 100644 --- a/test/Transforms/ArgumentPromotion/tail.ll +++ b/test/Transforms/ArgumentPromotion/tail.ll @@ -1,6 +1,8 @@ ; RUN: opt %s -argpromotion -S -o - | FileCheck %s ; PR14710 +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + %pair = type { i32, i32 } declare i8* @foo(%pair*) diff --git a/test/Transforms/ArgumentPromotion/variadic.ll b/test/Transforms/ArgumentPromotion/variadic.ll new file mode 100644 index 000000000000..0ae52b3bbbd1 --- /dev/null +++ b/test/Transforms/ArgumentPromotion/variadic.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -argpromotion -S | FileCheck %s + +; Unused arguments from variadic functions cannot be eliminated as that changes +; their classiciation according to the SysV amd64 ABI. Clang and other frontends +; bake in the classification when they use things like byval, as in this test. + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.tt0 = type { i64, i64 } +%struct.__va_list_tag = type { i32, i32, i8*, i8* } + +@t45 = internal global %struct.tt0 { i64 1335139741, i64 438042995 }, align 8 + +; Function Attrs: nounwind uwtable +define i32 @main(i32 %argc, i8** nocapture readnone %argv) #0 { +entry: + tail call void (i8*, i8*, i8*, i8*, i8*, ...)* @callee_t0f(i8* undef, i8* undef, i8* undef, i8* undef, i8* undef, %struct.tt0* byval align 8 @t45) + ret i32 0 +} + +; Function Attrs: nounwind uwtable +define internal void @callee_t0f(i8* nocapture readnone %tp13, i8* nocapture readnone %tp14, i8* nocapture readnone %tp15, i8* nocapture readnone %tp16, i8* nocapture readnone %tp17, ...) { +entry: + ret void +} + +; CHECK-LABEL: define internal void @callee_t0f(i8* nocapture readnone %tp13, i8* nocapture readnone %tp14, i8* nocapture readnone %tp15, i8* nocapture readnone %tp16, i8* nocapture readnone %tp17, ...) diff --git a/test/Transforms/AtomicExpandLoadLinked/ARM/atomic-expansion-v7.ll b/test/Transforms/AtomicExpand/ARM/atomic-expansion-v7.ll index 6a93016fc26e..282d42f75f05 100644 --- a/test/Transforms/AtomicExpandLoadLinked/ARM/atomic-expansion-v7.ll +++ b/test/Transforms/AtomicExpand/ARM/atomic-expansion-v7.ll @@ -1,8 +1,8 @@ -; RUN: opt -S -o - -mtriple=armv7-apple-ios7.0 -atomic-ll-sc %s | FileCheck %s +; RUN: opt -S -o - -mtriple=armv7-apple-ios7.0 -atomic-expand %s | FileCheck %s define i8 @test_atomic_xchg_i8(i8* %ptr, i8 %xchgend) { ; CHECK-LABEL: @test_atomic_xchg_i8 -; CHECK-NOT: fence +; CHECK-NOT: dmb ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) @@ -12,7 +12,7 @@ define i8 @test_atomic_xchg_i8(i8* %ptr, i8 %xchgend) { ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] ; CHECK: [[END]]: -; CHECK-NOT: fence +; CHECK-NOT: dmb ; CHECK: ret i8 [[OLDVAL]] %res = atomicrmw xchg i8* %ptr, i8 %xchgend monotonic ret i8 %res @@ -20,7 +20,7 @@ define i8 @test_atomic_xchg_i8(i8* %ptr, i8 %xchgend) { define i16 @test_atomic_add_i16(i16* %ptr, i16 %addend) { ; CHECK-LABEL: @test_atomic_add_i16 -; CHECK: fence release +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr) @@ -31,7 +31,7 @@ define i16 @test_atomic_add_i16(i16* %ptr, i16 %addend) { ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] ; CHECK: [[END]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: ret i16 [[OLDVAL]] %res = atomicrmw add i16* %ptr, i16 %addend seq_cst ret i16 %res @@ -39,7 +39,7 @@ define i16 @test_atomic_add_i16(i16* %ptr, i16 %addend) { define i32 @test_atomic_sub_i32(i32* %ptr, i32 %subend) { ; CHECK-LABEL: @test_atomic_sub_i32 -; CHECK-NOT: fence +; CHECK-NOT: dmb ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %ptr) @@ -48,7 +48,7 @@ define i32 @test_atomic_sub_i32(i32* %ptr, i32 %subend) { ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] ; CHECK: [[END]]: -; CHECK: fence acquire +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: ret i32 [[OLDVAL]] %res = atomicrmw sub i32* %ptr, i32 %subend acquire ret i32 %res @@ -56,7 +56,7 @@ define i32 @test_atomic_sub_i32(i32* %ptr, i32 %subend) { define i8 @test_atomic_and_i8(i8* %ptr, i8 %andend) { ; CHECK-LABEL: @test_atomic_and_i8 -; CHECK: fence release +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) @@ -67,7 +67,7 @@ define i8 @test_atomic_and_i8(i8* %ptr, i8 %andend) { ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] ; CHECK: [[END]]: -; CHECK-NOT: fence +; CHECK-NOT: dmb ; CHECK: ret i8 [[OLDVAL]] %res = atomicrmw and i8* %ptr, i8 %andend release ret i8 %res @@ -75,7 +75,7 @@ define i8 @test_atomic_and_i8(i8* %ptr, i8 %andend) { define i16 @test_atomic_nand_i16(i16* %ptr, i16 %nandend) { ; CHECK-LABEL: @test_atomic_nand_i16 -; CHECK: fence release +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr) @@ -87,7 +87,7 @@ define i16 @test_atomic_nand_i16(i16* %ptr, i16 %nandend) { ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] ; CHECK: [[END]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: ret i16 [[OLDVAL]] %res = atomicrmw nand i16* %ptr, i16 %nandend seq_cst ret i16 %res @@ -95,7 +95,7 @@ define i16 @test_atomic_nand_i16(i16* %ptr, i16 %nandend) { define i64 @test_atomic_or_i64(i64* %ptr, i64 %orend) { ; CHECK-LABEL: @test_atomic_or_i64 -; CHECK: fence release +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* @@ -115,7 +115,7 @@ define i64 @test_atomic_or_i64(i64* %ptr, i64 %orend) { ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] ; CHECK: [[END]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: ret i64 [[OLDVAL]] %res = atomicrmw or i64* %ptr, i64 %orend seq_cst ret i64 %res @@ -123,7 +123,7 @@ define i64 @test_atomic_or_i64(i64* %ptr, i64 %orend) { define i8 @test_atomic_xor_i8(i8* %ptr, i8 %xorend) { ; CHECK-LABEL: @test_atomic_xor_i8 -; CHECK: fence release +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) @@ -134,7 +134,7 @@ define i8 @test_atomic_xor_i8(i8* %ptr, i8 %xorend) { ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] ; CHECK: [[END]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: ret i8 [[OLDVAL]] %res = atomicrmw xor i8* %ptr, i8 %xorend seq_cst ret i8 %res @@ -142,7 +142,7 @@ define i8 @test_atomic_xor_i8(i8* %ptr, i8 %xorend) { define i8 @test_atomic_max_i8(i8* %ptr, i8 %maxend) { ; CHECK-LABEL: @test_atomic_max_i8 -; CHECK: fence release +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) @@ -154,7 +154,7 @@ define i8 @test_atomic_max_i8(i8* %ptr, i8 %maxend) { ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] ; CHECK: [[END]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: ret i8 [[OLDVAL]] %res = atomicrmw max i8* %ptr, i8 %maxend seq_cst ret i8 %res @@ -162,7 +162,7 @@ define i8 @test_atomic_max_i8(i8* %ptr, i8 %maxend) { define i8 @test_atomic_min_i8(i8* %ptr, i8 %minend) { ; CHECK-LABEL: @test_atomic_min_i8 -; CHECK: fence release +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) @@ -174,7 +174,7 @@ define i8 @test_atomic_min_i8(i8* %ptr, i8 %minend) { ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] ; CHECK: [[END]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: ret i8 [[OLDVAL]] %res = atomicrmw min i8* %ptr, i8 %minend seq_cst ret i8 %res @@ -182,7 +182,7 @@ define i8 @test_atomic_min_i8(i8* %ptr, i8 %minend) { define i8 @test_atomic_umax_i8(i8* %ptr, i8 %umaxend) { ; CHECK-LABEL: @test_atomic_umax_i8 -; CHECK: fence release +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) @@ -194,7 +194,7 @@ define i8 @test_atomic_umax_i8(i8* %ptr, i8 %umaxend) { ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] ; CHECK: [[END]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: ret i8 [[OLDVAL]] %res = atomicrmw umax i8* %ptr, i8 %umaxend seq_cst ret i8 %res @@ -202,7 +202,7 @@ define i8 @test_atomic_umax_i8(i8* %ptr, i8 %umaxend) { define i8 @test_atomic_umin_i8(i8* %ptr, i8 %uminend) { ; CHECK-LABEL: @test_atomic_umin_i8 -; CHECK: fence release +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) @@ -214,7 +214,7 @@ define i8 @test_atomic_umin_i8(i8* %ptr, i8 %uminend) { ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] ; CHECK: [[END]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: ret i8 [[OLDVAL]] %res = atomicrmw umin i8* %ptr, i8 %uminend seq_cst ret i8 %res @@ -222,7 +222,7 @@ define i8 @test_atomic_umin_i8(i8* %ptr, i8 %uminend) { define i8 @test_cmpxchg_i8_seqcst_seqcst(i8* %ptr, i8 %desired, i8 %newval) { ; CHECK-LABEL: @test_cmpxchg_i8_seqcst_seqcst -; CHECK: fence release +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: @@ -238,11 +238,11 @@ define i8 @test_cmpxchg_i8_seqcst_seqcst(i8* %ptr, i8 %desired, i8 %newval) { ; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] ; CHECK: [[SUCCESS_BB]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[DONE:.*]] ; CHECK: [[FAILURE_BB]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[DONE]] ; CHECK: [[DONE]]: @@ -256,7 +256,7 @@ define i8 @test_cmpxchg_i8_seqcst_seqcst(i8* %ptr, i8 %desired, i8 %newval) { define i16 @test_cmpxchg_i16_seqcst_monotonic(i16* %ptr, i16 %desired, i16 %newval) { ; CHECK-LABEL: @test_cmpxchg_i16_seqcst_monotonic -; CHECK: fence release +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: @@ -272,11 +272,11 @@ define i16 @test_cmpxchg_i16_seqcst_monotonic(i16* %ptr, i16 %desired, i16 %newv ; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] ; CHECK: [[SUCCESS_BB]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[DONE:.*]] ; CHECK: [[FAILURE_BB]]: -; CHECK-NOT: fence +; CHECK-NOT: dmb ; CHECK: br label %[[DONE]] ; CHECK: [[DONE]]: @@ -290,7 +290,7 @@ define i16 @test_cmpxchg_i16_seqcst_monotonic(i16* %ptr, i16 %desired, i16 %newv define i32 @test_cmpxchg_i32_acquire_acquire(i32* %ptr, i32 %desired, i32 %newval) { ; CHECK-LABEL: @test_cmpxchg_i32_acquire_acquire -; CHECK-NOT: fence +; CHECK-NOT: dmb ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: @@ -304,11 +304,11 @@ define i32 @test_cmpxchg_i32_acquire_acquire(i32* %ptr, i32 %desired, i32 %newva ; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] ; CHECK: [[SUCCESS_BB]]: -; CHECK: fence acquire +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[DONE:.*]] ; CHECK: [[FAILURE_BB]]: -; CHECK: fence acquire +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[DONE]] ; CHECK: [[DONE]]: @@ -322,7 +322,7 @@ define i32 @test_cmpxchg_i32_acquire_acquire(i32* %ptr, i32 %desired, i32 %newva define i64 @test_cmpxchg_i64_monotonic_monotonic(i64* %ptr, i64 %desired, i64 %newval) { ; CHECK-LABEL: @test_cmpxchg_i64_monotonic_monotonic -; CHECK-NOT: fence +; CHECK-NOT: dmb ; CHECK: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: @@ -347,11 +347,11 @@ define i64 @test_cmpxchg_i64_monotonic_monotonic(i64* %ptr, i64 %desired, i64 %n ; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] ; CHECK: [[SUCCESS_BB]]: -; CHECK-NOT: fence +; CHECK-NOT: dmb ; CHECK: br label %[[DONE:.*]] ; CHECK: [[FAILURE_BB]]: -; CHECK-NOT: fence +; CHECK-NOT: dmb ; CHECK: br label %[[DONE]] ; CHECK: [[DONE]]: @@ -361,4 +361,4 @@ define i64 @test_cmpxchg_i64_monotonic_monotonic(i64* %ptr, i64 %desired, i64 %n %pairold = cmpxchg i64* %ptr, i64 %desired, i64 %newval monotonic monotonic %old = extractvalue { i64, i1 } %pairold, 0 ret i64 %old -}
\ No newline at end of file +} diff --git a/test/Transforms/AtomicExpandLoadLinked/ARM/atomic-expansion-v8.ll b/test/Transforms/AtomicExpand/ARM/atomic-expansion-v8.ll index 8092c1010ff5..42d7b781006d 100644 --- a/test/Transforms/AtomicExpandLoadLinked/ARM/atomic-expansion-v8.ll +++ b/test/Transforms/AtomicExpand/ARM/atomic-expansion-v8.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -o - -mtriple=armv8-linux-gnueabihf -atomic-ll-sc %s | FileCheck %s +; RUN: opt -S -o - -mtriple=armv8-linux-gnueabihf -atomic-expand %s | FileCheck %s define i8 @test_atomic_xchg_i8(i8* %ptr, i8 %xchgend) { ; CHECK-LABEL: @test_atomic_xchg_i8 @@ -223,4 +223,4 @@ define i64 @test_cmpxchg_i64_monotonic_monotonic(i64* %ptr, i64 %desired, i64 %n %pairold = cmpxchg i64* %ptr, i64 %desired, i64 %newval monotonic monotonic %old = extractvalue { i64, i1 } %pairold, 0 ret i64 %old -}
\ No newline at end of file +} diff --git a/test/Transforms/AtomicExpandLoadLinked/ARM/cmpxchg-weak.ll b/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll index 07a4a7f26e62..54653000f5d8 100644 --- a/test/Transforms/AtomicExpandLoadLinked/ARM/cmpxchg-weak.ll +++ b/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll @@ -1,8 +1,9 @@ -; RUN: opt -atomic-ll-sc -S -mtriple=thumbv7s-apple-ios7.0 %s | FileCheck %s +; RUN: opt -atomic-expand -S -mtriple=thumbv7s-apple-ios7.0 %s | FileCheck %s define i32 @test_cmpxchg_seq_cst(i32* %addr, i32 %desired, i32 %new) { ; CHECK-LABEL: @test_cmpxchg_seq_cst -; CHECK: fence release +; Intrinsic for "dmb ishst" is then expected +; CHECK: call void @llvm.arm.dmb(i32 10) ; CHECK: br label %[[START:.*]] ; CHECK: [[START]]: @@ -16,11 +17,11 @@ define i32 @test_cmpxchg_seq_cst(i32* %addr, i32 %desired, i32 %new) { ; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB]] ; CHECK: [[SUCCESS_BB]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[END:.*]] ; CHECK: [[FAILURE_BB]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[END]] ; CHECK: [[END]]: @@ -34,7 +35,7 @@ define i32 @test_cmpxchg_seq_cst(i32* %addr, i32 %desired, i32 %new) { define i1 @test_cmpxchg_weak_fail(i32* %addr, i32 %desired, i32 %new) { ; CHECK-LABEL: @test_cmpxchg_weak_fail -; CHECK: fence release +; CHECK: call void @llvm.arm.dmb(i32 10) ; CHECK: br label %[[START:.*]] ; CHECK: [[START]]: @@ -48,11 +49,11 @@ define i1 @test_cmpxchg_weak_fail(i32* %addr, i32 %desired, i32 %new) { ; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] ; CHECK: [[SUCCESS_BB]]: -; CHECK: fence seq_cst +; CHECK: call void @llvm.arm.dmb(i32 11) ; CHECK: br label %[[END:.*]] ; CHECK: [[FAILURE_BB]]: -; CHECK-NOT: fence +; CHECK-NOT: dmb ; CHECK: br label %[[END]] ; CHECK: [[END]]: @@ -66,7 +67,7 @@ define i1 @test_cmpxchg_weak_fail(i32* %addr, i32 %desired, i32 %new) { define i32 @test_cmpxchg_monotonic(i32* %addr, i32 %desired, i32 %new) { ; CHECK-LABEL: @test_cmpxchg_monotonic -; CHECK-NOT: fence +; CHECK-NOT: dmb ; CHECK: br label %[[START:.*]] ; CHECK: [[START]]: @@ -80,11 +81,11 @@ define i32 @test_cmpxchg_monotonic(i32* %addr, i32 %desired, i32 %new) { ; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] ; CHECK: [[SUCCESS_BB]]: -; CHECK-NOT: fence +; CHECK-NOT: dmb ; CHECK: br label %[[END:.*]] ; CHECK: [[FAILURE_BB]]: -; CHECK-NOT: fence +; CHECK-NOT: dmb ; CHECK: br label %[[END]] ; CHECK: [[END]]: diff --git a/test/Transforms/AtomicExpandLoadLinked/ARM/lit.local.cfg b/test/Transforms/AtomicExpand/ARM/lit.local.cfg index 98c6700c209d..98c6700c209d 100644 --- a/test/Transforms/AtomicExpandLoadLinked/ARM/lit.local.cfg +++ b/test/Transforms/AtomicExpand/ARM/lit.local.cfg diff --git a/test/Transforms/BBVectorize/loop1.ll b/test/Transforms/BBVectorize/loop1.ll index ed7be15f7adf..ca361703adcb 100644 --- a/test/Transforms/BBVectorize/loop1.ll +++ b/test/Transforms/BBVectorize/loop1.ll @@ -83,7 +83,7 @@ for.body: ; preds = %for.body, %entry ; CHECK-UNRL: %add12 = fadd <2 x double> %add7, %mul11 ; CHECK-UNRL: %4 = bitcast double* %arrayidx14 to <2 x double>* ; CHECK-UNRL: store <2 x double> %add12, <2 x double>* %4, align 8 -; CHECK-UNRL: %indvars.iv.next.1 = add i64 %indvars.iv, 2 +; CHECK-UNRL: %indvars.iv.next.1 = add nsw i64 %indvars.iv, 2 ; CHECK-UNRL: %lftr.wideiv.1 = trunc i64 %indvars.iv.next.1 to i32 ; CHECK-UNRL: %exitcond.1 = icmp eq i32 %lftr.wideiv.1, 10 ; CHECK-UNRL: br i1 %exitcond.1, label %for.end, label %for.body diff --git a/test/Transforms/BBVectorize/metadata.ll b/test/Transforms/BBVectorize/metadata.ll index ac7297dd5417..874fbb87967c 100644 --- a/test/Transforms/BBVectorize/metadata.ll +++ b/test/Transforms/BBVectorize/metadata.ll @@ -41,9 +41,9 @@ entry: ; CHECK: ret void } -!0 = metadata !{i64 0, i64 2} -!1 = metadata !{i64 3, i64 5} +!0 = !{i64 0, i64 2} +!1 = !{i64 3, i64 5} -!2 = metadata !{ float 5.0 } -!3 = metadata !{ float 2.5 } +!2 = !{ float 5.0 } +!3 = !{ float 2.5 } diff --git a/test/Transforms/BranchFolding/2007-10-19-InlineAsmDirectives.ll b/test/Transforms/BranchFolding/2007-10-19-InlineAsmDirectives.ll index 598ea0e354e1..d4b94fe62c71 100644 --- a/test/Transforms/BranchFolding/2007-10-19-InlineAsmDirectives.ll +++ b/test/Transforms/BranchFolding/2007-10-19-InlineAsmDirectives.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -std-compile-opts -o - | llc -no-integrated-as -o - | grep bork_directive | wc -l | grep 2 +; RUN: opt < %s -O3 -o - | llc -no-integrated-as -o - | grep bork_directive | wc -l | grep 2 ;; We don't want branch folding to fold asm directives. diff --git a/test/Transforms/CodeGenPrepare/AArch64/lit.local.cfg b/test/Transforms/CodeGenPrepare/AArch64/lit.local.cfg new file mode 100644 index 000000000000..cec29af5bbe4 --- /dev/null +++ b/test/Transforms/CodeGenPrepare/AArch64/lit.local.cfg @@ -0,0 +1,3 @@ +if not 'AArch64' in config.root.targets: + config.unsupported = True + diff --git a/test/Transforms/CodeGenPrepare/AArch64/trunc-weird-user.ll b/test/Transforms/CodeGenPrepare/AArch64/trunc-weird-user.ll new file mode 100644 index 000000000000..b4e6a409288f --- /dev/null +++ b/test/Transforms/CodeGenPrepare/AArch64/trunc-weird-user.ll @@ -0,0 +1,36 @@ +; RUN: opt -S -codegenprepare -mtriple=arm64-apple-ios7.0 %s | FileCheck %s + +%foo = type { i8 } + +define %foo @test_merge(i32 %in) { +; CHECK-LABEL: @test_merge + + ; CodeGenPrepare was requesting the EVT for { i8 } to determine + ; whether the insertvalue user of the trunc was legal. This + ; asserted. + +; CHECK: insertvalue %foo undef, i8 %byte, 0 + %lobit = lshr i32 %in, 31 + %byte = trunc i32 %lobit to i8 + %struct = insertvalue %foo undef, i8 %byte, 0 + ret %"foo" %struct +} + +define i64* @test_merge_PR21548(i32 %a, i64* %p1, i64* %p2, i64* %p3) { +; CHECK-LABEL: @test_merge_PR21548 + %as = lshr i32 %a, 3 + %Tr = trunc i32 %as to i1 + br i1 %Tr, label %BB2, label %BB3 + +BB2: + ; Similarly to above: + ; CodeGenPrepare was requesting the EVT for i8* to determine + ; whether the select user of the trunc was legal. This asserted. + +; CHECK: select i1 {{%.*}}, i64* %p1, i64* %p2 + %p = select i1 %Tr, i64* %p1, i64* %p2 + ret i64* %p + +BB3: + ret i64* %p3 +} diff --git a/test/Transforms/ConstProp/trunc_vec.ll b/test/Transforms/ConstProp/trunc_vec.ll new file mode 100644 index 000000000000..99db329cdd2b --- /dev/null +++ b/test/Transforms/ConstProp/trunc_vec.ll @@ -0,0 +1,9 @@ +; RUN: opt -constprop < %s + +; Make sure we don't crash on this one + +define <8 x i8> @test_truc_vec() { + %x = bitcast <2 x i64> <i64 1, i64 2> to <8 x i16> + %y = trunc <8 x i16> %x to <8 x i8> + ret <8 x i8> %y +} diff --git a/test/Transforms/CorrelatedValuePropagation/icmp.ll b/test/Transforms/CorrelatedValuePropagation/icmp.ll new file mode 100644 index 000000000000..c2863ffda0fb --- /dev/null +++ b/test/Transforms/CorrelatedValuePropagation/icmp.ll @@ -0,0 +1,63 @@ +; RUN: opt -correlated-propagation -S %s | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.10.0" + +; Function Attrs: noreturn +declare void @check1(i1) #1 + +; Function Attrs: noreturn +declare void @check2(i1) #1 + +; Make sure we propagate the value of %tmp35 to the true/false cases +; CHECK-LABEL: @test1 +; CHECK: call void @check1(i1 false) +; CHECK: call void @check2(i1 true) +define void @test1(i64 %tmp35) { +bb: + %tmp36 = icmp sgt i64 %tmp35, 0 + br i1 %tmp36, label %bb_true, label %bb_false + +bb_true: + %tmp47 = icmp slt i64 %tmp35, 0 + tail call void @check1(i1 %tmp47) #4 + unreachable + +bb_false: + %tmp48 = icmp sle i64 %tmp35, 0 + tail call void @check2(i1 %tmp48) #4 + unreachable +} + +; Function Attrs: noreturn +; This is the same as test1 but with a diamond to ensure we +; get %tmp36 from both true and false BBs. +; CHECK-LABEL: @test2 +; CHECK: call void @check1(i1 false) +; CHECK: call void @check2(i1 true) +define void @test2(i64 %tmp35, i1 %inner_cmp) { +bb: + %tmp36 = icmp sgt i64 %tmp35, 0 + br i1 %tmp36, label %bb_true, label %bb_false + +bb_true: + br i1 %inner_cmp, label %inner_true, label %inner_false + +inner_true: + br label %merge + +inner_false: + br label %merge + +merge: + %tmp47 = icmp slt i64 %tmp35, 0 + tail call void @check1(i1 %tmp47) #0 + unreachable + +bb_false: + %tmp48 = icmp sle i64 %tmp35, 0 + tail call void @check2(i1 %tmp48) #4 + unreachable +} + +attributes #4 = { noreturn } diff --git a/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll b/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll index 26982db8322d..dd283aebc1d4 100644 --- a/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll +++ b/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll @@ -4,24 +4,24 @@ define i8* @vfs_addname(i8* %name, i32 %len, i32 %hash, i32 %flags) nounwind ssp { entry: - call void @llvm.dbg.value(metadata !{i8* %name}, i64 0, metadata !0) - call void @llvm.dbg.value(metadata !{i32 %len}, i64 0, metadata !10) - call void @llvm.dbg.value(metadata !{i32 %hash}, i64 0, metadata !11) - call void @llvm.dbg.value(metadata !{i32 %flags}, i64 0, metadata !12) + call void @llvm.dbg.value(metadata i8* %name, i64 0, metadata !0, metadata !{}) + call void @llvm.dbg.value(metadata i32 %len, i64 0, metadata !10, metadata !{}) + call void @llvm.dbg.value(metadata i32 %hash, i64 0, metadata !11, metadata !{}) + call void @llvm.dbg.value(metadata i32 %flags, i64 0, metadata !12, metadata !{}) ; CHECK: call fastcc i8* @add_name_internal(i8* %name, i32 %hash) [[NUW:#[0-9]+]], !dbg !{{[0-9]+}} %0 = call fastcc i8* @add_name_internal(i8* %name, i32 %len, i32 %hash, i8 zeroext 0, i32 %flags) nounwind, !dbg !13 ; <i8*> [#uses=1] ret i8* %0, !dbg !13 } -declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone define internal fastcc i8* @add_name_internal(i8* %name, i32 %len, i32 %hash, i8 zeroext %extra, i32 %flags) noinline nounwind ssp { entry: - call void @llvm.dbg.value(metadata !{i8* %name}, i64 0, metadata !15) - call void @llvm.dbg.value(metadata !{i32 %len}, i64 0, metadata !20) - call void @llvm.dbg.value(metadata !{i32 %hash}, i64 0, metadata !21) - call void @llvm.dbg.value(metadata !{i8 %extra}, i64 0, metadata !22) - call void @llvm.dbg.value(metadata !{i32 %flags}, i64 0, metadata !23) + call void @llvm.dbg.value(metadata i8* %name, i64 0, metadata !15, metadata !{}) + call void @llvm.dbg.value(metadata i32 %len, i64 0, metadata !20, metadata !{}) + call void @llvm.dbg.value(metadata i32 %hash, i64 0, metadata !21, metadata !{}) + call void @llvm.dbg.value(metadata i8 %extra, i64 0, metadata !22, metadata !{}) + call void @llvm.dbg.value(metadata i32 %flags, i64 0, metadata !23, metadata !{}) %0 = icmp eq i32 %hash, 0, !dbg !24 ; <i1> [#uses=1] br i1 %0, label %bb, label %bb1, !dbg !24 @@ -36,7 +36,7 @@ bb2: ; preds = %bb1, %bb ret i8* %.0, !dbg !27 } -declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone ; CHECK: attributes #0 = { nounwind ssp } ; CHECK: attributes #1 = { nounwind readnone } @@ -45,34 +45,34 @@ declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone !llvm.dbg.cu = !{!3} !llvm.module.flags = !{!30} -!0 = metadata !{i32 524545, metadata !1, metadata !"name", metadata !2, i32 8, metadata !6} ; [ DW_TAG_arg_variable ] -!1 = metadata !{i32 524334, metadata !28, metadata !2, metadata !"vfs_addname", metadata !"vfs_addname", metadata !"vfs_addname", i32 12, metadata !4, i1 false, i1 true, i32 0, i32 0, null, i1 false, i32 0, null, null, null, null, i32 0} ; [ DW_TAG_subprogram ] -!2 = metadata !{i32 524329, metadata !28} ; [ DW_TAG_file_type ] -!3 = metadata !{i32 524305, metadata !28, i32 1, metadata !"4.2.1 (Based on Apple Inc. build 5658) (LLVM build 9999)", i1 true, metadata !"", i32 0, metadata !29, metadata !29, null, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!4 = metadata !{i32 524309, metadata !28, metadata !2, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !5, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!5 = metadata !{metadata !6, metadata !6, metadata !9, metadata !9, metadata !9} -!6 = metadata !{i32 524303, metadata !28, metadata !2, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !7} ; [ DW_TAG_pointer_type ] -!7 = metadata !{i32 524326, metadata !28, metadata !2, metadata !"", i32 0, i64 8, i64 8, i64 0, i32 0, metadata !8} ; [ DW_TAG_const_type ] -!8 = metadata !{i32 524324, metadata !28, metadata !2, metadata !"char", i32 0, i64 8, i64 8, i64 0, i32 0, i32 6} ; [ DW_TAG_base_type ] -!9 = metadata !{i32 524324, metadata !28, metadata !2, metadata !"unsigned int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 7} ; [ DW_TAG_base_type ] -!10 = metadata !{i32 524545, metadata !1, metadata !"len", metadata !2, i32 9, metadata !9} ; [ DW_TAG_arg_variable ] -!11 = metadata !{i32 524545, metadata !1, metadata !"hash", metadata !2, i32 10, metadata !9} ; [ DW_TAG_arg_variable ] -!12 = metadata !{i32 524545, metadata !1, metadata !"flags", metadata !2, i32 11, metadata !9} ; [ DW_TAG_arg_variable ] -!13 = metadata !{i32 13, i32 0, metadata !14, null} -!14 = metadata !{i32 524299, metadata !28, metadata !1, i32 12, i32 0, i32 0} ; [ DW_TAG_lexical_block ] -!15 = metadata !{i32 524545, metadata !16, metadata !"name", metadata !2, i32 17, metadata !6} ; [ DW_TAG_arg_variable ] -!16 = metadata !{i32 524334, metadata !28, metadata !2, metadata !"add_name_internal", metadata !"add_name_internal", metadata !"add_name_internal", i32 22, metadata !17, i1 true, i1 true, i32 0, i32 0, null, i1 false, i32 0, null, null, null, null, i32 0} ; [ DW_TAG_subprogram ] -!17 = metadata !{i32 524309, metadata !28, metadata !2, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !18, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!18 = metadata !{metadata !6, metadata !6, metadata !9, metadata !9, metadata !19, metadata !9} -!19 = metadata !{i32 524324, metadata !28, metadata !2, metadata !"unsigned char", i32 0, i64 8, i64 8, i64 0, i32 0, i32 8} ; [ DW_TAG_base_type ] -!20 = metadata !{i32 524545, metadata !16, metadata !"len", metadata !2, i32 18, metadata !9} ; [ DW_TAG_arg_variable ] -!21 = metadata !{i32 524545, metadata !16, metadata !"hash", metadata !2, i32 19, metadata !9} ; [ DW_TAG_arg_variable ] -!22 = metadata !{i32 524545, metadata !16, metadata !"extra", metadata !2, i32 20, metadata !19} ; [ DW_TAG_arg_variable ] -!23 = metadata !{i32 524545, metadata !16, metadata !"flags", metadata !2, i32 21, metadata !9} ; [ DW_TAG_arg_variable ] -!24 = metadata !{i32 23, i32 0, metadata !25, null} -!25 = metadata !{i32 524299, metadata !28, metadata !16, i32 22, i32 0, i32 0} ; [ DW_TAG_lexical_block ] -!26 = metadata !{i32 24, i32 0, metadata !25, null} -!27 = metadata !{i32 26, i32 0, metadata !25, null} -!28 = metadata !{metadata !"tail.c", metadata !"/Users/echeng/LLVM/radars/r7927803/"} -!29 = metadata !{i32 0} -!30 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x101\00name\008\000", !1, !2, !6} ; [ DW_TAG_arg_variable ] +!1 = !{!"0x2e\00vfs_addname\00vfs_addname\00vfs_addname\0012\000\001\000\006\000\000\000", !28, !2, !4, null, null, null, null, null} ; [ DW_TAG_subprogram ] +!2 = !{!"0x29", !28} ; [ DW_TAG_file_type ] +!3 = !{!"0x11\001\004.2.1 (Based on Apple Inc. build 5658) (LLVM build 9999)\001\00\000\00\000", !28, !29, !29, null, null, null} ; [ DW_TAG_compile_unit ] +!4 = !{!"0x15\00\000\000\000\000\000\000", !28, !2, null, !5, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!5 = !{!6, !6, !9, !9, !9} +!6 = !{!"0xf\00\000\0064\0064\000\000", !28, !2, !7} ; [ DW_TAG_pointer_type ] +!7 = !{!"0x26\00\000\008\008\000\000", !28, !2, !8} ; [ DW_TAG_const_type ] +!8 = !{!"0x24\00char\000\008\008\000\000\006", !28, !2} ; [ DW_TAG_base_type ] +!9 = !{!"0x24\00unsigned int\000\0032\0032\000\000\007", !28, !2} ; [ DW_TAG_base_type ] +!10 = !{!"0x101\00len\009\000", !1, !2, !9} ; [ DW_TAG_arg_variable ] +!11 = !{!"0x101\00hash\0010\000", !1, !2, !9} ; [ DW_TAG_arg_variable ] +!12 = !{!"0x101\00flags\0011\000", !1, !2, !9} ; [ DW_TAG_arg_variable ] +!13 = !MDLocation(line: 13, scope: !14) +!14 = !{!"0xb\0012\000\000", !28, !1} ; [ DW_TAG_lexical_block ] +!15 = !{!"0x101\00name\0017\000", !16, !2, !6} ; [ DW_TAG_arg_variable ] +!16 = !{!"0x2e\00add_name_internal\00add_name_internal\00add_name_internal\0022\001\001\000\006\000\000\000", !28, !2, !17, null, null, null, null, null} ; [ DW_TAG_subprogram ] +!17 = !{!"0x15\00\000\000\000\000\000\000", !28, !2, null, !18, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!18 = !{!6, !6, !9, !9, !19, !9} +!19 = !{!"0x24\00unsigned char\000\008\008\000\000\008", !28, !2} ; [ DW_TAG_base_type ] +!20 = !{!"0x101\00len\0018\000", !16, !2, !9} ; [ DW_TAG_arg_variable ] +!21 = !{!"0x101\00hash\0019\000", !16, !2, !9} ; [ DW_TAG_arg_variable ] +!22 = !{!"0x101\00extra\0020\000", !16, !2, !19} ; [ DW_TAG_arg_variable ] +!23 = !{!"0x101\00flags\0021\000", !16, !2, !9} ; [ DW_TAG_arg_variable ] +!24 = !MDLocation(line: 23, scope: !25) +!25 = !{!"0xb\0022\000\000", !28, !16} ; [ DW_TAG_lexical_block ] +!26 = !MDLocation(line: 24, scope: !25) +!27 = !MDLocation(line: 26, scope: !25) +!28 = !{!"tail.c", !"/Users/echeng/LLVM/radars/r7927803/"} +!29 = !{i32 0} +!30 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/DeadArgElim/dbginfo.ll b/test/Transforms/DeadArgElim/dbginfo.ll index 7bdcbf5c0623..5bbf821ef213 100644 --- a/test/Transforms/DeadArgElim/dbginfo.ll +++ b/test/Transforms/DeadArgElim/dbginfo.ll @@ -1,65 +1,70 @@ ; RUN: opt -deadargelim -S < %s | FileCheck %s ; PR14016 -; Check that debug info metadata for subprograms stores pointers to -; updated LLVM functions. +; Built with clang (then manually running -mem2reg with opt) from the following source: +; static void f1(int, ...) { +; } +; +; void f2() { +; f1(1); +; } -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" -target triple = "x86_64-unknown-linux-gnu" +; Test both varargs removal and removal of a traditional dead arg together, to +; test both the basic functionality, and a particular wrinkle involving updating +; the function->debug info mapping on update to ensure it's accurate when used +; again for the next removal. -@x = global i32 0, align 4 +; CHECK: void ()* @_ZL2f1iz, {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [f1] -define void @_Z3runv() uwtable { -entry: - call void @_ZN12_GLOBAL__N_18dead_argEPv(i8* null), !dbg !10 - call void (...)* @_ZN12_GLOBAL__N_111dead_varargEz(), !dbg !12 - ret void, !dbg !13 -} +; Check that debug info metadata for subprograms stores pointers to +; updated LLVM functions. -; Argument will be deleted -define internal void @_ZN12_GLOBAL__N_18dead_argEPv(i8* %foo) nounwind uwtable { +; Function Attrs: uwtable +define void @_Z2f2v() #0 { entry: - %0 = load i32* @x, align 4, !dbg !14 - %inc = add nsw i32 %0, 1, !dbg !14 - store i32 %inc, i32* @x, align 4, !dbg !14 + call void (i32, ...)* @_ZL2f1iz(i32 1), !dbg !15 ret void, !dbg !16 } -; Vararg will be deleted -define internal void @_ZN12_GLOBAL__N_111dead_varargEz(...) nounwind uwtable { +; Function Attrs: nounwind uwtable +define internal void @_ZL2f1iz(i32, ...) #1 { entry: - %0 = load i32* @x, align 4, !dbg !17 - %inc = add nsw i32 %0, 1, !dbg !17 - store i32 %inc, i32* @x, align 4, !dbg !17 - ret void, !dbg !19 + call void @llvm.dbg.value(metadata i32 %0, i64 0, metadata !17, metadata !18), !dbg !19 + ret void, !dbg !20 } -!llvm.dbg.cu = !{!0} -!llvm.module.flags = !{!21} - -!0 = metadata !{i32 786449, metadata !20, i32 4, metadata !"clang version 3.2 (trunk 165305)", i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !3, metadata !1, metadata !1, metadata !""} ; [ DW_TAG_compile_unit ] [/home/samsonov/tmp/clang-di/test.cc] [DW_LANG_C_plus_plus] -!1 = metadata !{i32 0} -!3 = metadata !{metadata !5, metadata !8, metadata !9} -!5 = metadata !{i32 786478, metadata !20, metadata !6, metadata !"run", metadata !"run", metadata !"", i32 8, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @_Z3runv, null, null, metadata !1, i32 8} ; [ DW_TAG_subprogram ] [line 8] [def] [run] -!6 = metadata !{i32 786473, metadata !20} ; [ DW_TAG_file_type ] -!7 = metadata !{i32 786453, i32 0, null, i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !1, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!8 = metadata !{i32 786478, metadata !20, metadata !6, metadata !"dead_vararg", metadata !"dead_vararg", metadata !"", i32 5, metadata !7, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (...)* @_ZN12_GLOBAL__N_111dead_varargEz, null, null, metadata !1, i32 5} ; [ DW_TAG_subprogram ] [line 5] [local] [def] [dead_vararg] +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) #2 -; CHECK: metadata !"dead_vararg"{{.*}}void ()* @_ZN12_GLOBAL__N_111dead_varargEz +; Function Attrs: nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2 -!9 = metadata !{i32 786478, metadata !20, metadata !6, metadata !"dead_arg", metadata !"dead_arg", metadata !"", i32 4, metadata !7, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (i8*)* @_ZN12_GLOBAL__N_18dead_argEPv, null, null, metadata !1, i32 4} ; [ DW_TAG_subprogram ] [line 4] [local] [def] [dead_arg] +attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind readnone } -; CHECK: metadata !"dead_arg"{{.*}}void ()* @_ZN12_GLOBAL__N_18dead_argEPv +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!12, !13} +!llvm.ident = !{!14} -!10 = metadata !{i32 8, i32 14, metadata !11, null} -!11 = metadata !{i32 786443, metadata !20, metadata !5, i32 8, i32 12, i32 0} ; [ DW_TAG_lexical_block ] [/home/samsonov/tmp/clang-di/test.cc] -!12 = metadata !{i32 8, i32 27, metadata !11, null} -!13 = metadata !{i32 8, i32 42, metadata !11, null} -!14 = metadata !{i32 4, i32 28, metadata !15, null} -!15 = metadata !{i32 786443, metadata !20, metadata !9, i32 4, i32 26, i32 2} ; [ DW_TAG_lexical_block ] [/home/samsonov/tmp/clang-di/test.cc] -!16 = metadata !{i32 4, i32 33, metadata !15, null} -!17 = metadata !{i32 5, i32 25, metadata !18, null} -!18 = metadata !{i32 786443, metadata !20, metadata !8, i32 5, i32 23, i32 1} ; [ DW_TAG_lexical_block ] [/home/samsonov/tmp/clang-di/test.cc] -!19 = metadata !{i32 5, i32 30, metadata !18, null} -!20 = metadata !{metadata !"test.cc", metadata !"/home/samsonov/tmp/clang-di"} -!21 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x11\004\00clang version 3.6.0 \000\00\000\00\001", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [/tmp/dbginfo/dbg.cpp] [DW_LANG_C_plus_plus] +!1 = !{!"dbg.cpp", !"/tmp/dbginfo"} +!2 = !{} +!3 = !{!4, !8} +!4 = !{!"0x2e\00f2\00f2\00_Z2f2v\004\000\001\000\000\00256\000\004", !1, !5, !6, null, void ()* @_Z2f2v, null, null, !2} ; [ DW_TAG_subprogram ] [line 4] [def] [f2] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [/tmp/dbginfo/dbg.cpp] +!6 = !{!"0x15\00\000\000\000\000\000\000", null, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{null} +!8 = !{!"0x2e\00f1\00f1\00_ZL2f1iz\001\001\001\000\000\00256\000\001", !1, !5, !9, null, void (i32, ...)* @_ZL2f1iz, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [local] [def] [f1] +!9 = !{!"0x15\00\000\000\000\000\000\000", null, null, null, !10, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!10 = !{null, !11, null} +!11 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!12 = !{i32 2, !"Dwarf Version", i32 4} +!13 = !{i32 2, !"Debug Info Version", i32 2} +!14 = !{!"clang version 3.6.0 "} +!15 = !MDLocation(line: 5, column: 3, scope: !4) +!16 = !MDLocation(line: 6, column: 1, scope: !4) +!17 = !{!"0x101\00\0016777217\000", !8, !5, !11} ; [ DW_TAG_arg_variable ] [line 1] +!18 = !{!"0x102"} ; [ DW_TAG_expression ] +!19 = !MDLocation(line: 1, column: 19, scope: !8) +!20 = !MDLocation(line: 2, column: 1, scope: !8) diff --git a/test/Transforms/DeadArgElim/dead_vaargs.ll b/test/Transforms/DeadArgElim/dead_vaargs.ll index db3135c8393b..c8189c66b48c 100644 --- a/test/Transforms/DeadArgElim/dead_vaargs.ll +++ b/test/Transforms/DeadArgElim/dead_vaargs.ll @@ -1,12 +1,36 @@ -; RUN: opt < %s -deadargelim -S | not grep 47 -; RUN: opt < %s -deadargelim -S | not grep 1.0 +; RUN: opt < %s -deadargelim -S | FileCheck %s define i32 @bar(i32 %A) { - %tmp4 = tail call i32 (i32, ...)* @foo( i32 %A, i32 %A, i32 %A, i32 %A, i64 47, double 1.000000e+00 ) ; <i32> [#uses=1] - ret i32 %tmp4 + call void (i32, ...)* @thunk(i32 %A, i64 47, double 1.000000e+00) + %a = call i32 (i32, ...)* @has_vastart(i32 %A, i64 47, double 1.000000e+00) + %b = call i32 (i32, ...)* @no_vastart( i32 %A, i32 %A, i32 %A, i32 %A, i64 47, double 1.000000e+00 ) + %c = add i32 %a, %b + ret i32 %c } +; CHECK-LABEL: define i32 @bar +; CHECK: call void (i32, ...)* @thunk(i32 %A, i64 47, double 1.000000e+00) +; CHECK: call i32 (i32, ...)* @has_vastart(i32 %A, i64 47, double 1.000000e+00) +; CHECK: call i32 @no_vastart(i32 %A) -define internal i32 @foo(i32 %X, ...) { - ret i32 %X +declare void @thunk_target(i32 %X, ...) + +define internal void @thunk(i32 %X, ...) { + musttail call void(i32, ...)* @thunk_target(i32 %X, ...) + ret void +} +; CHECK-LABEL: define internal void @thunk(i32 %X, ...) +; CHECK: musttail call void (i32, ...)* @thunk_target(i32 %X, ...) + +define internal i32 @has_vastart(i32 %X, ...) { + %valist = alloca i8 + call void @llvm.va_start(i8* %valist) + ret i32 %X } +; CHECK-LABEL: define internal i32 @has_vastart(i32 %X, ...) +declare void @llvm.va_start(i8*) + +define internal i32 @no_vastart(i32 %X, ...) { + ret i32 %X +} +; CHECK-LABEL: define internal i32 @no_vastart(i32 %X) diff --git a/test/Transforms/DeadStoreElimination/2011-03-25-DSEMiscompile.ll b/test/Transforms/DeadStoreElimination/2011-03-25-DSEMiscompile.ll index 079eec43bf85..39d53584dc37 100644 --- a/test/Transforms/DeadStoreElimination/2011-03-25-DSEMiscompile.ll +++ b/test/Transforms/DeadStoreElimination/2011-03-25-DSEMiscompile.ll @@ -5,9 +5,9 @@ target triple = "i386-apple-darwin9.8" @A = external global [0 x i32] -declare cc10 void @Func2(i32*, i32*, i32*, i32) +declare ghccc void @Func2(i32*, i32*, i32*, i32) -define cc10 void @Func1(i32* noalias %Arg1, i32* noalias %Arg2, i32* %Arg3, i32 %Arg4) { +define ghccc void @Func1(i32* noalias %Arg1, i32* noalias %Arg2, i32* %Arg3, i32 %Arg4) { entry: store i32 add (i32 ptrtoint ([0 x i32]* @A to i32), i32 1), i32* %Arg2 ; CHECK: store i32 add (i32 ptrtoint ([0 x i32]* @A to i32), i32 1), i32* %Arg2 @@ -18,6 +18,6 @@ entry: %ln2gE = bitcast i32* %ln2gD to double* store double %ln2gB, double* %ln2gE ; CHECK: store double %ln2gB, double* %ln2gE - tail call cc10 void @Func2(i32* %Arg1, i32* %Arg2, i32* %Arg3, i32 %Arg4) nounwind + tail call ghccc void @Func2(i32* %Arg1, i32* %Arg2, i32* %Arg3, i32 %Arg4) nounwind ret void } diff --git a/test/Transforms/DeadStoreElimination/atomic.ll b/test/Transforms/DeadStoreElimination/atomic.ll index 2e84298ad400..af303fa983ee 100644 --- a/test/Transforms/DeadStoreElimination/atomic.ll +++ b/test/Transforms/DeadStoreElimination/atomic.ll @@ -5,7 +5,7 @@ target triple = "x86_64-apple-macosx10.7.0" ; Sanity tests for atomic stores. ; Note that it turns out essentially every transformation DSE does is legal on -; atomic ops, just some transformations are not allowed across them. +; atomic ops, just some transformations are not allowed across release-acquire pairs. @x = common global i32 0, align 4 @y = common global i32 0, align 4 @@ -13,35 +13,32 @@ target triple = "x86_64-apple-macosx10.7.0" declare void @randomop(i32*) ; DSE across unordered store (allowed) -define void @test1() nounwind uwtable ssp { -; CHECK: test1 +define void @test1() { +; CHECK-LABEL: test1 ; CHECK-NOT: store i32 0 ; CHECK: store i32 1 -entry: store i32 0, i32* @x store atomic i32 0, i32* @y unordered, align 4 store i32 1, i32* @x ret void } -; DSE across seq_cst load (allowed in theory; not implemented ATM) -define i32 @test2() nounwind uwtable ssp { -; CHECK: test2 -; CHECK: store i32 0 +; DSE across seq_cst load (allowed) +define i32 @test2() { +; CHECK-LABEL: test2 +; CHECK-NOT: store i32 0 ; CHECK: store i32 1 -entry: store i32 0, i32* @x %x = load atomic i32* @y seq_cst, align 4 store i32 1, i32* @x ret i32 %x } -; DSE across seq_cst store (store before atomic store must not be removed) -define void @test3() nounwind uwtable ssp { -; CHECK: test3 -; CHECK: store i32 +; DSE across seq_cst store (allowed) +define void @test3() { +; CHECK-LABEL: test3 +; CHECK-NOT: store i32 0 ; CHECK: store atomic i32 2 -entry: store i32 0, i32* @x store atomic i32 2, i32* @y seq_cst, align 4 store i32 1, i32* @x @@ -49,32 +46,29 @@ entry: } ; DSE remove unordered store (allowed) -define void @test4() nounwind uwtable ssp { -; CHECK: test4 +define void @test4() { +; CHECK-LABEL: test4 ; CHECK-NOT: store atomic ; CHECK: store i32 1 -entry: store atomic i32 0, i32* @x unordered, align 4 store i32 1, i32* @x ret void } ; DSE unordered store overwriting non-atomic store (allowed) -define void @test5() nounwind uwtable ssp { -; CHECK: test5 +define void @test5() { +; CHECK-LABEL: test5 ; CHECK: store atomic i32 1 -entry: store i32 0, i32* @x store atomic i32 1, i32* @x unordered, align 4 ret void } ; DSE no-op unordered atomic store (allowed) -define void @test6() nounwind uwtable ssp { -; CHECK: test6 +define void @test6() { +; CHECK-LABEL: test6 ; CHECK-NOT: store ; CHECK: ret void -entry: %x = load atomic i32* @x unordered, align 4 store atomic i32 %x, i32* @x unordered, align 4 ret void @@ -82,10 +76,9 @@ entry: ; DSE seq_cst store (be conservative; DSE doesn't have infrastructure ; to reason about atomic operations). -define void @test7() nounwind uwtable ssp { -; CHECK: test7 -; CHECK: store atomic -entry: +define void @test7() { +; CHECK-LABEL: test7 +; CHECK: store atomic %a = alloca i32 store atomic i32 0, i32* %a seq_cst, align 4 ret void @@ -93,11 +86,10 @@ entry: ; DSE and seq_cst load (be conservative; DSE doesn't have infrastructure ; to reason about atomic operations). -define i32 @test8() nounwind uwtable ssp { -; CHECK: test8 +define i32 @test8() { +; CHECK-LABEL: test8 ; CHECK: store -; CHECK: load atomic -entry: +; CHECK: load atomic %a = alloca i32 call void @randomop(i32* %a) store i32 0, i32* %a, align 4 @@ -105,3 +97,82 @@ entry: ret i32 %x } +; DSE across monotonic load (allowed as long as the eliminated store isUnordered) +define i32 @test9() { +; CHECK-LABEL: test9 +; CHECK-NOT: store i32 0 +; CHECK: store i32 1 + store i32 0, i32* @x + %x = load atomic i32* @y monotonic, align 4 + store i32 1, i32* @x + ret i32 %x +} + +; DSE across monotonic store (allowed as long as the eliminated store isUnordered) +define void @test10() { +; CHECK-LABEL: test10 +; CHECK-NOT: store i32 0 +; CHECK: store i32 1 + store i32 0, i32* @x + store atomic i32 42, i32* @y monotonic, align 4 + store i32 1, i32* @x + ret void +} + +; DSE across monotonic load (forbidden since the eliminated store is atomic) +define i32 @test11() { +; CHECK-LABEL: test11 +; CHECK: store atomic i32 0 +; CHECK: store atomic i32 1 + store atomic i32 0, i32* @x monotonic, align 4 + %x = load atomic i32* @y monotonic, align 4 + store atomic i32 1, i32* @x monotonic, align 4 + ret i32 %x +} + +; DSE across monotonic store (forbidden since the eliminated store is atomic) +define void @test12() { +; CHECK-LABEL: test12 +; CHECK: store atomic i32 0 +; CHECK: store atomic i32 1 + store atomic i32 0, i32* @x monotonic, align 4 + store atomic i32 42, i32* @y monotonic, align 4 + store atomic i32 1, i32* @x monotonic, align 4 + ret void +} + +; DSE is allowed across a pair of an atomic read and then write. +define i32 @test13() { +; CHECK-LABEL: test13 +; CHECK-NOT: store i32 0 +; CHECK: store i32 1 + store i32 0, i32* @x + %x = load atomic i32* @y seq_cst, align 4 + store atomic i32 %x, i32* @y seq_cst, align 4 + store i32 1, i32* @x + ret i32 %x +} + +; Same if it is acquire-release instead of seq_cst/seq_cst +define i32 @test14() { +; CHECK-LABEL: test14 +; CHECK-NOT: store i32 0 +; CHECK: store i32 1 + store i32 0, i32* @x + %x = load atomic i32* @y acquire, align 4 + store atomic i32 %x, i32* @y release, align 4 + store i32 1, i32* @x + ret i32 %x +} + +; But DSE is not allowed across a release-acquire pair. +define i32 @test15() { +; CHECK-LABEL: test15 +; CHECK: store i32 0 +; CHECK: store i32 1 + store i32 0, i32* @x + store atomic i32 0, i32* @y release, align 4 + %x = load atomic i32* @y acquire, align 4 + store i32 1, i32* @x + ret i32 %x +} diff --git a/test/Transforms/DeadStoreElimination/const-pointers.ll b/test/Transforms/DeadStoreElimination/const-pointers.ll index c90d824b34c1..3e772d79c70a 100644 --- a/test/Transforms/DeadStoreElimination/const-pointers.ll +++ b/test/Transforms/DeadStoreElimination/const-pointers.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -dse -S < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" %t = type { i32 } diff --git a/test/Transforms/DeadStoreElimination/inst-limits.ll b/test/Transforms/DeadStoreElimination/inst-limits.ll index 9df88014e5c6..3ef560723387 100644 --- a/test/Transforms/DeadStoreElimination/inst-limits.ll +++ b/test/Transforms/DeadStoreElimination/inst-limits.ll @@ -1,4 +1,5 @@ ; RUN: opt -S -dse < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; If there are two stores to the same location, DSE should be able to remove ; the first store if the two stores are separated by no more than 98 @@ -117,7 +118,7 @@ entry: ; Insert a meaningless dbg.value intrinsic; it should have no ; effect on the working of DSE in any way. - call void @llvm.dbg.value(metadata !12, i64 0, metadata !10) + call void @llvm.dbg.value(metadata i32* undef, i64 0, metadata !10, metadata !{}) ; CHECK: store i32 -1, i32* @x, align 4 store i32 -1, i32* @x, align 4 @@ -239,23 +240,23 @@ entry: } ; Function Attrs: nounwind readnone -declare void @llvm.dbg.value(metadata, i64, metadata) +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!11, !13} -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.4", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !9, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/home/tmp/test.c] [DW_LANG_C99] -!1 = metadata !{metadata !"test.c", metadata !"/home/tmp"} -!2 = metadata !{i32 0} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"test_within_limit", metadata !"test_within_limit", metadata !"", i32 3, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 ()* @test_within_limit, null, null, metadata !2, i32 4} ; [ DW_TAG_subprogram ] [line 3] [def] [scope 4] [test] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/home/tmp/test.c] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{metadata !8} -!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] -!9 = metadata !{metadata !10} -!10 = metadata !{i32 786484, i32 0, null, metadata !"x", metadata !"x", metadata !"", metadata !5, i32 1, metadata !8, i32 0, i32 1, i32* @x, null} ; [ DW_TAG_variable ] [x] [line 1] [def] -!11 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!12 = metadata !{i32* undef} +!0 = !{!"0x11\004\00clang version 3.4\001\00\000\00\000", !1, !2, !2, !3, !9, !2} ; [ DW_TAG_compile_unit ] [/home/tmp/test.c] [DW_LANG_C99] +!1 = !{!"test.c", !"/home/tmp"} +!2 = !{i32 0} +!3 = !{!4} +!4 = !{!"0x2e\00test_within_limit\00test_within_limit\00\003\000\001\000\006\00256\000\004", !1, !5, !6, null, i32 ()* @test_within_limit, null, null, !2} ; [ DW_TAG_subprogram ] [line 3] [def] [scope 4] [test] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [/home/tmp/test.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{!8} +!8 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!9 = !{!10} +!10 = !{!"0x34\00x\00x\00\001\000\001", null, !5, !8, i32* @x, null} ; [ DW_TAG_variable ] [x] [line 1] [def] +!11 = !{i32 2, !"Dwarf Version", i32 4} +!12 = !{i32* undef} -!13 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!13 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/DeadStoreElimination/no-targetdata.ll b/test/Transforms/DeadStoreElimination/no-targetdata.ll index c0c7c58d4ead..25395330bf37 100644 --- a/test/Transforms/DeadStoreElimination/no-targetdata.ll +++ b/test/Transforms/DeadStoreElimination/no-targetdata.ll @@ -1,15 +1,21 @@ ; RUN: opt -basicaa -dse -S < %s | FileCheck %s -declare void @test1f() - -define void @test1(i32* noalias %p) { - store i32 1, i32* %p - call void @test1f() - store i32 2, i32 *%p - ret void -; CHECK-LABEL: define void @test1( -; CHECK-NOT: store -; CHECK-NEXT: call void -; CHECK-NEXT: store i32 2 -; CHECK-NEXT: ret void +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind + +define void @fn(i8* nocapture %buf) #0 { +entry: + +; We would not eliminate the first memcpy with data layout, and we should not +; eliminate it without data layout. +; CHECK-LABEL: @fn +; CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64 +; CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64 +; CHECK: ret void + + %arrayidx = getelementptr i8* %buf, i64 18 + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, i64 18, i32 1, i1 false) + store i8 1, i8* %arrayidx, align 1 + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, i64 18, i32 1, i1 false) + ret void } + diff --git a/test/Transforms/DebugIR/crash.ll b/test/Transforms/DebugIR/crash.ll deleted file mode 100644 index f4a88d7234cb..000000000000 --- a/test/Transforms/DebugIR/crash.ll +++ /dev/null @@ -1,42 +0,0 @@ -; ModuleID = 'crash.c' -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" -target triple = "x86_64-pc-linux-gnu" - -@.str = private unnamed_addr constant [18 x i8] c"Hello, segfault!\0A\00", align 1 -@.str1 = private unnamed_addr constant [14 x i8] c"Now crash %d\0A\00", align 1 - -; Function Attrs: nounwind uwtable -define i32 @main(i32 %argc, i8** %argv) #0 { - %1 = alloca i32, align 4 ;CHECK: !dbg - %2 = alloca i32, align 4 ;CHECK-NEXT: !dbg - %3 = alloca i8**, align 8 ;CHECK-NEXT: !dbg - %null_ptr = alloca i32*, align 8 ;CHECK-NEXT: !dbg - store i32 0, i32* %1 ;CHECK-NEXT: !dbg - store i32 %argc, i32* %2, align 4 ;CHECK-NEXT: !dbg - store i8** %argv, i8*** %3, align 8 ;CHECK-NEXT: !dbg - store i32* null, i32** %null_ptr, align 8 ;CHECK-NEXT: !dbg - %4 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([18 x i8]* @.str, i32 0, i32 0)) ;CHECK-NEXT: !dbg - %5 = load i32** %null_ptr, align 8 ;CHECK-NEXT: !dbg - %6 = load i32* %5, align 4 ;CHECK-NEXT: !dbg - %7 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([14 x i8]* @.str1, i32 0, i32 0), i32 %6) ;CHECK-NEXT: !dbg - %8 = load i32* %2, align 4 ;CHECK-NEXT: !dbg - ret i32 %8 ;CHECK-NEXT: !dbg -} - -declare i32 @printf(i8*, ...) #1 - -attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } - -; CHECK: = metadata !{i32 14, -; CHECK-NEXT: = metadata !{i32 15, -; CHECK-NEXT: = metadata !{i32 16, -; CHECK-NEXT: = metadata !{i32 17, -; CHECK-NEXT: = metadata !{i32 18, -; CHECK-NEXT: = metadata !{i32 19, -; CHECK-NEXT: = metadata !{i32 20, -; CHECK-NEXT: = metadata !{i32 21, -; CHECK-NEXT: = metadata !{i32 22, -; CHECK-NEXT: = metadata !{i32 23, - -; RUN: opt %s -debug-ir -S | FileCheck %s diff --git a/test/Transforms/DebugIR/exception.ll b/test/Transforms/DebugIR/exception.ll deleted file mode 100644 index 2436d38968c9..000000000000 --- a/test/Transforms/DebugIR/exception.ll +++ /dev/null @@ -1,127 +0,0 @@ -; ModuleID = 'exception.cpp' -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" -target triple = "x86_64-pc-linux-gnu" - -@_ZTIi = external constant i8* - -; Function Attrs: uwtable -define i32 @main(i32 %argc, i8** %argv) #0 { - %1 = alloca i32, align 4 ; CHECK: !dbg - %2 = alloca i32, align 4 ; CHECK-NEXT: !dbg - %3 = alloca i8**, align 8 ; CHECK-NEXT: !dbg - %4 = alloca i8* ; CHECK-NEXT: !dbg - %5 = alloca i32 ; CHECK-NEXT: !dbg - %e = alloca i32, align 4 ; CHECK-NEXT: !dbg - %6 = alloca i32 ; CHECK-NEXT: !dbg - store i32 0, i32* %1 ; CHECK-NEXT: !dbg - store i32 %argc, i32* %2, align 4 ; CHECK-NEXT: !dbg - store i8** %argv, i8*** %3, align 8 ; CHECK-NEXT: !dbg - %7 = call i8* @__cxa_allocate_exception(i64 4) #2 ; CHECK-NEXT: !dbg - %8 = bitcast i8* %7 to i32* ; CHECK-NEXT: !dbg - %9 = load i32* %2, align 4 ; CHECK-NEXT: !dbg - store i32 %9, i32* %8 ; CHECK-NEXT: !dbg - invoke void @__cxa_throw(i8* %7, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #3 - to label %31 unwind label %10 ; CHECK: !dbg - -; <label>:10 ; preds = %0 - %11 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) - catch i8* bitcast (i8** @_ZTIi to i8*) ; CHECK: !dbg - %12 = extractvalue { i8*, i32 } %11, 0 ; CHECK-NEXT: !dbg - store i8* %12, i8** %4 ; CHECK-NEXT: !dbg - %13 = extractvalue { i8*, i32 } %11, 1 ; CHECK-NEXT: !dbg - store i32 %13, i32* %5 ; CHECK-NEXT: !dbg - br label %14 ; CHECK-NEXT: !dbg - -; <label>:14 ; preds = %10 - %15 = load i32* %5 ; CHECK: !dbg - %16 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #2 ; CHECK-NEXT: !dbg - %17 = icmp eq i32 %15, %16 ; CHECK-NEXT: !dbg - br i1 %17, label %18, label %26 ; CHECK-NEXT: !dbg - -; <label>:18 ; preds = %14 - %19 = load i8** %4 ; CHECK: !dbg - %20 = call i8* @__cxa_begin_catch(i8* %19) #2 ; CHECK-NEXT: !dbg - %21 = bitcast i8* %20 to i32* ; CHECK-NEXT: !dbg - %22 = load i32* %21, align 4 ; CHECK-NEXT: !dbg - store i32 %22, i32* %e, align 4 ; CHECK-NEXT: !dbg - %23 = load i32* %e, align 4 ; CHECK-NEXT: !dbg - store i32 %23, i32* %1 ; CHECK-NEXT: !dbg - store i32 1, i32* %6 ; CHECK-NEXT: !dbg - call void @__cxa_end_catch() #2 ; CHECK-NEXT: !dbg - br label %24 ; CHECK-NEXT: !dbg - -; <label>:24 ; preds = %18 - %25 = load i32* %1 ; CHECK: !dbg - ret i32 %25 ; CHECK-NEXT: !dbg - -; <label>:26 ; preds = %14 - %27 = load i8** %4 ; CHECK: !dbg - %28 = load i32* %5 ; CHECK-NEXT: !dbg - %29 = insertvalue { i8*, i32 } undef, i8* %27, 0 ; CHECK-NEXT: !dbg - %30 = insertvalue { i8*, i32 } %29, i32 %28, 1 ; CHECK-NEXT: !dbg - resume { i8*, i32 } %30 ; CHECK-NEXT: !dbg - -; <label>:31 ; preds = %0 - unreachable ; CHECK: !dbg -} - -declare i8* @__cxa_allocate_exception(i64) - -declare void @__cxa_throw(i8*, i8*, i8*) - -declare i32 @__gxx_personality_v0(...) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #1 - -declare i8* @__cxa_begin_catch(i8*) - -declare void @__cxa_end_catch() - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind readnone } -attributes #2 = { nounwind } -attributes #3 = { noreturn } -; CHECK: = metadata !{i32 16, -; CHECK-NEXT: = metadata !{i32 17, -; CHECK-NEXT: = metadata !{i32 18, -; CHECK-NEXT: = metadata !{i32 19, -; CHECK-NEXT: = metadata !{i32 20, -; CHECK-NEXT: = metadata !{i32 21, -; CHECK-NEXT: = metadata !{i32 22, -; CHECK-NEXT: = metadata !{i32 24, - -; CHECK-NEXT: = metadata !{i32 28, -; CHECK-NEXT: = metadata !{i32 29, -; CHECK-NEXT: = metadata !{i32 30, -; CHECK-NEXT: = metadata !{i32 31, -; CHECK-NEXT: = metadata !{i32 32, -; CHECK-NEXT: = metadata !{i32 33, - -; CHECK-NEXT: = metadata !{i32 36, -; CHECK-NEXT: = metadata !{i32 37, -; CHECK-NEXT: = metadata !{i32 38, -; CHECK-NEXT: = metadata !{i32 39, - -; CHECK-NEXT: = metadata !{i32 42, -; CHECK-NEXT: = metadata !{i32 43, -; CHECK-NEXT: = metadata !{i32 44, -; CHECK-NEXT: = metadata !{i32 45, -; CHECK-NEXT: = metadata !{i32 46, -; CHECK-NEXT: = metadata !{i32 47, -; CHECK-NEXT: = metadata !{i32 48, -; CHECK-NEXT: = metadata !{i32 49, -; CHECK-NEXT: = metadata !{i32 50, -; CHECK-NEXT: = metadata !{i32 51, - -; CHECK-NEXT: = metadata !{i32 54, -; CHECK-NEXT: = metadata !{i32 55, - -; CHECK-NEXT: = metadata !{i32 58, -; CHECK-NEXT: = metadata !{i32 59, -; CHECK-NEXT: = metadata !{i32 60, -; CHECK-NEXT: = metadata !{i32 61, -; CHECK-NEXT: = metadata !{i32 62, -; CHECK-NEXT: = metadata !{i32 65, - -; RUN: opt %s -debug-ir -S | FileCheck %s diff --git a/test/Transforms/DebugIR/function.ll b/test/Transforms/DebugIR/function.ll deleted file mode 100644 index dba073de37e9..000000000000 --- a/test/Transforms/DebugIR/function.ll +++ /dev/null @@ -1,51 +0,0 @@ -; ModuleID = 'function.c' -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" -target triple = "x86_64-pc-linux-gnu" - -; Function Attrs: nounwind uwtable -define void @blah(i32* %i) #0 { - %1 = alloca i32*, align 8 ; CHECK: !dbg - store i32* %i, i32** %1, align 8 ; CHECK-NEXT: !dbg - %2 = load i32** %1, align 8 ; CHECK-NEXT: !dbg - %3 = load i32* %2, align 4 ; CHECK-NEXT: !dbg - %4 = add nsw i32 %3, 1 ; CHECK-NEXT: !dbg - store i32 %4, i32* %2, align 4 ; CHECK-NEXT: !dbg - ret void ; CHECK-NEXT: !dbg -} - -; Function Attrs: nounwind uwtable -define i32 @main(i32 %argc, i8** %argv) #0 { - %1 = alloca i32, align 4 ; CHECK: !dbg - %2 = alloca i32, align 4 ; CHECK-NEXT: !dbg - %3 = alloca i8**, align 8 ; CHECK-NEXT: !dbg - %i = alloca i32, align 4 ; CHECK-NEXT: !dbg - store i32 0, i32* %1 ; CHECK-NEXT: !dbg - store i32 %argc, i32* %2, align 4 ; CHECK-NEXT: !dbg - store i8** %argv, i8*** %3, align 8 ; CHECK-NEXT: !dbg - store i32 7, i32* %i, align 4 ; CHECK-NEXT: !dbg - call void @blah(i32* %i) ; CHECK-NEXT: !dbg - %4 = load i32* %i, align 4 ; CHECK-NEXT: !dbg - ret i32 %4 ; CHECK-NEXT: !dbg -} - -attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } -; CHECK: = metadata !{i32 8, -; CHECK-NEXT: = metadata !{i32 9, -; CHECK-NEXT: = metadata !{i32 10, -; CHECK-NEXT: = metadata !{i32 11, -; CHECK-NEXT: = metadata !{i32 12, -; CHECK-NEXT: = metadata !{i32 13, - -; CHECK-NEXT: = metadata !{i32 18, -; CHECK-NEXT: = metadata !{i32 19, -; CHECK-NEXT: = metadata !{i32 20, -; CHECK-NEXT: = metadata !{i32 21, -; CHECK-NEXT: = metadata !{i32 22, -; CHECK-NEXT: = metadata !{i32 23, -; CHECK-NEXT: = metadata !{i32 24, -; CHECK-NEXT: = metadata !{i32 25, -; CHECK-NEXT: = metadata !{i32 26, -; CHECK-NEXT: = metadata !{i32 27, -; CHECK-NEXT: = metadata !{i32 28, - -; RUN: opt %s -debug-ir -S | FileCheck %s diff --git a/test/Transforms/DebugIR/simple-addrspace.ll b/test/Transforms/DebugIR/simple-addrspace.ll deleted file mode 100644 index 6bea9b269f57..000000000000 --- a/test/Transforms/DebugIR/simple-addrspace.ll +++ /dev/null @@ -1,13 +0,0 @@ -; RUN: opt -debug-ir -S %s -o - | FileCheck %s - -target datalayout = "e-p:64:64:64-p1:16:16:16" - -define void @foo(i32 addrspace(1)*) nounwind { - ret void -} - -; Make sure the pointer size is 16 - -; CHECK: metadata !"i32 addrspace(1)*", i32 0, i64 16, i64 2, i64 0, i32 0 - - diff --git a/test/Transforms/DebugIR/simple.ll b/test/Transforms/DebugIR/simple.ll deleted file mode 100644 index 3b188958261f..000000000000 --- a/test/Transforms/DebugIR/simple.ll +++ /dev/null @@ -1,25 +0,0 @@ -; ModuleID = 'simple.c' -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" -target triple = "x86_64-pc-linux-gnu" - -; Function Attrs: nounwind uwtable -define i32 @main(i32 %argc, i8** %argv) #0 { - %1 = alloca i32, align 4 ; CHECK: !dbg - %2 = alloca i32, align 4 ; CHECK-NEXT: !dbg - %3 = alloca i8**, align 8 ; CHECK-NEXT: !dbg - store i32 0, i32* %1 ; CHECK-NEXT: !dbg - store i32 %argc, i32* %2, align 4 ; CHECK-NEXT: !dbg - store i8** %argv, i8*** %3, align 8 ; CHECK-NEXT: !dbg - %4 = load i32* %2, align 4 ; CHECK-NEXT: !dbg - ret i32 %4 ; CHECK-NEXT: !dbg -} - -attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } - -; CHECK: = metadata !{i32 10, -; CHECK-NEXT: = metadata !{i32 11, -; CHECK-NEXT: = metadata !{i32 12, -; CHECK-NEXT: = metadata !{i32 13, -; CHECK-NEXT: = metadata !{i32 14, - -; RUN: opt %s -debug-ir -S | FileCheck %s diff --git a/test/Transforms/DebugIR/struct.ll b/test/Transforms/DebugIR/struct.ll deleted file mode 100644 index 8db3dbebe90b..000000000000 --- a/test/Transforms/DebugIR/struct.ll +++ /dev/null @@ -1,24 +0,0 @@ -; ModuleID = 'struct.cpp' -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" -target triple = "x86_64-pc-linux-gnu" - -%struct.blah = type { i32, float, i8 } - -; Function Attrs: nounwind uwtable -define i32 @main() #0 { - %1 = alloca i32, align 4 ; CHECK: !dbg - %b = alloca %struct.blah, align 4 ; CHECK-NEXT: !dbg - store i32 0, i32* %1 ; CHECK-NEXT: !dbg - %2 = getelementptr inbounds %struct.blah* %b, i32 0, i32 0 ; CHECK-NEXT: !dbg - %3 = load i32* %2, align 4 ; CHECK-NEXT: !dbg - ret i32 %3 ; CHECK-NEXT: !dbg -} - -attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } - -; CHECK: = metadata !{i32 11, -; CHECK-NEXT: = metadata !{i32 12, -; CHECK-NEXT: = metadata !{i32 13, -; CHECK-NEXT: = metadata !{i32 14, - -; RUN: opt %s -debug-ir -S | FileCheck %s diff --git a/test/Transforms/DebugIR/vector.ll b/test/Transforms/DebugIR/vector.ll deleted file mode 100644 index 50d99ac2254f..000000000000 --- a/test/Transforms/DebugIR/vector.ll +++ /dev/null @@ -1,93 +0,0 @@ -; ModuleID = 'vector.cpp' -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" -target triple = "x86_64-pc-linux-gnu" - -; Function Attrs: noinline nounwind uwtable -define <4 x float> @_Z3fooDv2_fS_(double %a.coerce, double %b.coerce) #0 { - %1 = alloca <2 x float>, align 8 ; CHECK: !dbg - %2 = alloca <2 x float>, align 8 ; CHECK-NEXT: !dbg - %3 = alloca <2 x float>, align 8 ; CHECK-NEXT: !dbg - %4 = alloca <2 x float>, align 8 ; CHECK-NEXT: !dbg - %c = alloca <4 x float>, align 16 ; CHECK-NEXT: !dbg - %5 = bitcast <2 x float>* %1 to double* ; CHECK-NEXT: !dbg - store double %a.coerce, double* %5, align 1 ; CHECK-NEXT: !dbg - %a = load <2 x float>* %1, align 8 ; CHECK-NEXT: !dbg - store <2 x float> %a, <2 x float>* %2, align 8 ; CHECK-NEXT: !dbg - %6 = bitcast <2 x float>* %3 to double* ; CHECK-NEXT: !dbg - store double %b.coerce, double* %6, align 1 ; CHECK-NEXT: !dbg - %b = load <2 x float>* %3, align 8 ; CHECK-NEXT: !dbg - store <2 x float> %b, <2 x float>* %4, align 8 ; CHECK-NEXT: !dbg - %7 = load <2 x float>* %2, align 8 ; CHECK-NEXT: !dbg - %8 = load <4 x float>* %c, align 16 ; CHECK-NEXT: !dbg - %9 = shufflevector <2 x float> %7, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> ; CHECK-NEXT: !dbg - %10 = shufflevector <4 x float> %8, <4 x float> %9, <4 x i32> <i32 4, i32 1, i32 5, i32 3> ; CHECK-NEXT: !dbg - store <4 x float> %10, <4 x float>* %c, align 16 ; CHECK-NEXT: !dbg - %11 = load <2 x float>* %4, align 8 ; CHECK-NEXT: !dbg - %12 = load <4 x float>* %c, align 16 ; CHECK-NEXT: !dbg - %13 = shufflevector <2 x float> %11, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> ; CHECK-NEXT: !dbg - %14 = shufflevector <4 x float> %12, <4 x float> %13, <4 x i32> <i32 0, i32 4, i32 2, i32 5> ; CHECK-NEXT: !dbg - store <4 x float> %14, <4 x float>* %c, align 16 ; CHECK-NEXT: !dbg - %15 = load <4 x float>* %c, align 16 ; CHECK-NEXT: !dbg - ret <4 x float> %15 ; CHECK-NEXT: !dbg -} - -; Function Attrs: nounwind uwtable -define i32 @main() #1 { - %1 = alloca i32, align 4 ; CHECK: !dbg - %a = alloca <2 x float>, align 8 ; CHECK-NEXT: !dbg - %b = alloca <2 x float>, align 8 ; CHECK-NEXT: !dbg - %x = alloca <4 x float>, align 16 ; CHECK-NEXT: !dbg - %2 = alloca <2 x float>, align 8 ; CHECK-NEXT: !dbg - %3 = alloca <2 x float>, align 8 ; CHECK-NEXT: !dbg - store i32 0, i32* %1 ; CHECK-NEXT: !dbg - store <2 x float> <float 1.000000e+00, float 2.000000e+00>, <2 x float>* %a, align 8 ; CHECK-NEXT: !dbg - store <2 x float> <float 1.000000e+00, float 2.000000e+00>, <2 x float>* %b, align 8 ; CHECK-NEXT: !dbg - %4 = load <2 x float>* %a, align 8 ; CHECK-NEXT: !dbg - %5 = load <2 x float>* %b, align 8 ; CHECK-NEXT: !dbg - store <2 x float> %4, <2 x float>* %2, align 8 ; CHECK-NEXT: !dbg - %6 = bitcast <2 x float>* %2 to double* ; CHECK-NEXT: !dbg - %7 = load double* %6, align 1 ; CHECK-NEXT: !dbg - store <2 x float> %5, <2 x float>* %3, align 8 ; CHECK-NEXT: !dbg - %8 = bitcast <2 x float>* %3 to double* ; CHECK-NEXT: !dbg - %9 = load double* %8, align 1 ; CHECK-NEXT: !dbg - %10 = call <4 x float> @_Z3fooDv2_fS_(double %7, double %9) ; CHECK-NEXT: !dbg - store <4 x float> %10, <4 x float>* %x, align 16 ; CHECK-NEXT: !dbg - %11 = load <4 x float>* %x, align 16 ; CHECK-NEXT: !dbg - %12 = extractelement <4 x float> %11, i32 0 ; CHECK-NEXT: !dbg - %13 = load <4 x float>* %x, align 16 ; CHECK-NEXT: !dbg - %14 = extractelement <4 x float> %13, i32 1 ; CHECK-NEXT: !dbg - %15 = fadd float %12, %14 ; CHECK-NEXT: !dbg - %16 = load <4 x float>* %x, align 16 ; CHECK-NEXT: !dbg - %17 = extractelement <4 x float> %16, i32 2 ; CHECK-NEXT: !dbg - %18 = fadd float %15, %17 ; CHECK-NEXT: !dbg - %19 = load <4 x float>* %x, align 16 ; CHECK-NEXT: !dbg - %20 = extractelement <4 x float> %19, i32 3 ; CHECK-NEXT: !dbg - %21 = fadd float %18, %20 ; CHECK-NEXT: !dbg - %22 = fptosi float %21 to i32 ; CHECK-NEXT: !dbg - ret i32 %22 ; CHECK-NEXT: !dbg -} - -attributes #0 = { noinline nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } - -; CHECK: = metadata !{i32 13, -; CHECK-NEXT: = metadata !{i32 14, -; CHECK-NEXT: = metadata !{i32 15, -; CHECK-NEXT: = metadata !{i32 16, -; CHECK-NEXT: = metadata !{i32 17, -; CHECK-NEXT: = metadata !{i32 18, -; CHECK-NEXT: = metadata !{i32 19, -; CHECK-NEXT: = metadata !{i32 20, -; CHECK-NEXT: = metadata !{i32 21, -; CHECK-NEXT: = metadata !{i32 22, -; CHECK-NEXT: = metadata !{i32 23, -; CHECK-NEXT: = metadata !{i32 24, -; CHECK-NEXT: = metadata !{i32 25, -; CHECK-NEXT: = metadata !{i32 26, -; CHECK-NEXT: = metadata !{i32 27, -; CHECK-NEXT: = metadata !{i32 28, -; CHECK-NEXT: = metadata !{i32 29, -; CHECK-NEXT: = metadata !{i32 30, -; CHECK-NEXT: = metadata !{i32 31, - -; RUN: opt %s -debug-ir -S | FileCheck %s diff --git a/test/Transforms/EarlyCSE/basic.ll b/test/Transforms/EarlyCSE/basic.ll index 80704df9852e..155d36f60e21 100644 --- a/test/Transforms/EarlyCSE/basic.ll +++ b/test/Transforms/EarlyCSE/basic.ll @@ -1,5 +1,6 @@ ; RUN: opt < %s -S -early-cse | FileCheck %s +declare void @llvm.assume(i1) nounwind ; CHECK-LABEL: @test1( define void @test1(i8 %V, i32 *%P) { @@ -42,6 +43,16 @@ define i32 @test2(i32 *%P) { ; CHECK: ret i32 0 } +; CHECK-LABEL: @test2a( +define i32 @test2a(i32 *%P, i1 %b) { + %V1 = load i32* %P + tail call void @llvm.assume(i1 %b) + %V2 = load i32* %P + %Diff = sub i32 %V1, %V2 + ret i32 %Diff + ; CHECK: ret i32 0 +} + ;; Cross block load value numbering. ; CHECK-LABEL: @test3( define i32 @test3(i32 *%P, i1 %Cond) { @@ -58,6 +69,22 @@ F: ; CHECK: ret i32 0 } +; CHECK-LABEL: @test3a( +define i32 @test3a(i32 *%P, i1 %Cond, i1 %b) { + %V1 = load i32* %P + br i1 %Cond, label %T, label %F +T: + store i32 4, i32* %P + ret i32 42 +F: + tail call void @llvm.assume(i1 %b) + %V2 = load i32* %P + %Diff = sub i32 %V1, %V2 + ret i32 %Diff + ; CHECK: F: + ; CHECK: ret i32 0 +} + ;; Cross block load value numbering stops when stores happen. ; CHECK-LABEL: @test4( define i32 @test4(i32 *%P, i1 %Cond) { @@ -97,6 +124,15 @@ define i32 @test6(i32 *%P) { ; CHECK: ret i32 42 } +; CHECK-LABEL: @test6a( +define i32 @test6a(i32 *%P, i1 %b) { + store i32 42, i32* %P + tail call void @llvm.assume(i1 %b) + %V1 = load i32* %P + ret i32 %V1 + ; CHECK: ret i32 42 +} + ;; Trivial dead store elimination. ; CHECK-LABEL: @test7( define void @test7(i32 *%P) { @@ -118,4 +154,42 @@ define i32 @test8(i32 *%P) { ; CHECK: ret i32 0 } +;; Trivial DSE can't be performed across a readonly call. The call +;; can observe the earlier write. +; CHECK-LABEL: @test9( +define i32 @test9(i32 *%P) { + store i32 4, i32* %P + %V1 = call i32 @func(i32* %P) readonly + store i32 5, i32* %P + ret i32 %V1 + ; CHECK: store i32 4, i32* %P + ; CHECK-NEXT: %V1 = call i32 @func(i32* %P) + ; CHECK-NEXT: store i32 5, i32* %P + ; CHECK-NEXT: ret i32 %V1 +} + +;; Trivial DSE can be performed across a readnone call. +; CHECK-LABEL: @test10 +define i32 @test10(i32 *%P) { + store i32 4, i32* %P + %V1 = call i32 @func(i32* %P) readnone + store i32 5, i32* %P + ret i32 %V1 + ; CHECK-NEXT: %V1 = call i32 @func(i32* %P) + ; CHECK-NEXT: store i32 5, i32* %P + ; CHECK-NEXT: ret i32 %V1 +} + +;; Trivial dead store elimination - should work for an entire series of dead stores too. +; CHECK-LABEL: @test11( +define void @test11(i32 *%P) { + store i32 42, i32* %P + store i32 43, i32* %P + store i32 44, i32* %P + store i32 45, i32* %P + ret void + ; CHECK-NEXT: store i32 45 + ; CHECK-NEXT: ret void +} + diff --git a/test/Transforms/FunctionAttrs/optnone-simple.ll b/test/Transforms/FunctionAttrs/optnone-simple.ll new file mode 100644 index 000000000000..9d0f8e3710a6 --- /dev/null +++ b/test/Transforms/FunctionAttrs/optnone-simple.ll @@ -0,0 +1,135 @@ +; RUN: opt -O3 -S < %s | FileCheck %s +; Show 'optnone' suppresses optimizations. + +; Two attribute groups that differ only by 'optnone'. +; 'optnone' requires 'noinline' so #0 is 'noinline' by itself, +; even though it would otherwise be irrelevant to this example. +attributes #0 = { noinline } +attributes #1 = { noinline optnone } + +; int iadd(int a, int b){ return a + b; } + +define i32 @iadd_optimize(i32 %a, i32 %b) #0 { +entry: + %a.addr = alloca i32, align 4 + %b.addr = alloca i32, align 4 + store i32 %a, i32* %a.addr, align 4 + store i32 %b, i32* %b.addr, align 4 + %0 = load i32* %a.addr, align 4 + %1 = load i32* %b.addr, align 4 + %add = add nsw i32 %0, %1 + ret i32 %add +} + +; CHECK-LABEL: @iadd_optimize +; CHECK-NOT: alloca +; CHECK-NOT: store +; CHECK-NOT: load +; CHECK: ret + +define i32 @iadd_optnone(i32 %a, i32 %b) #1 { +entry: + %a.addr = alloca i32, align 4 + %b.addr = alloca i32, align 4 + store i32 %a, i32* %a.addr, align 4 + store i32 %b, i32* %b.addr, align 4 + %0 = load i32* %a.addr, align 4 + %1 = load i32* %b.addr, align 4 + %add = add nsw i32 %0, %1 + ret i32 %add +} + +; CHECK-LABEL: @iadd_optnone +; CHECK: alloca i32 +; CHECK: alloca i32 +; CHECK: store i32 +; CHECK: store i32 +; CHECK: load i32 +; CHECK: load i32 +; CHECK: add nsw i32 +; CHECK: ret i32 + +; float fsub(float a, float b){ return a - b; } + +define float @fsub_optimize(float %a, float %b) #0 { +entry: + %a.addr = alloca float, align 4 + %b.addr = alloca float, align 4 + store float %a, float* %a.addr, align 4 + store float %b, float* %b.addr, align 4 + %0 = load float* %a.addr, align 4 + %1 = load float* %b.addr, align 4 + %sub = fsub float %0, %1 + ret float %sub +} + +; CHECK-LABEL: @fsub_optimize +; CHECK-NOT: alloca +; CHECK-NOT: store +; CHECK-NOT: load +; CHECK: ret + +define float @fsub_optnone(float %a, float %b) #1 { +entry: + %a.addr = alloca float, align 4 + %b.addr = alloca float, align 4 + store float %a, float* %a.addr, align 4 + store float %b, float* %b.addr, align 4 + %0 = load float* %a.addr, align 4 + %1 = load float* %b.addr, align 4 + %sub = fsub float %0, %1 + ret float %sub +} + +; CHECK-LABEL: @fsub_optnone +; CHECK: alloca float +; CHECK: alloca float +; CHECK: store float +; CHECK: store float +; CHECK: load float +; CHECK: load float +; CHECK: fsub float +; CHECK: ret float + +; typedef float __attribute__((ext_vector_type(4))) float4; +; float4 vmul(float4 a, float4 b){ return a * b; } + +define <4 x float> @vmul_optimize(<4 x float> %a, <4 x float> %b) #0 { +entry: + %a.addr = alloca <4 x float>, align 16 + %b.addr = alloca <4 x float>, align 16 + store <4 x float> %a, <4 x float>* %a.addr, align 16 + store <4 x float> %b, <4 x float>* %b.addr, align 16 + %0 = load <4 x float>* %a.addr, align 16 + %1 = load <4 x float>* %b.addr, align 16 + %mul = fmul <4 x float> %0, %1 + ret <4 x float> %mul +} + +; CHECK-LABEL: @vmul_optimize +; CHECK-NOT: alloca +; CHECK-NOT: store +; CHECK-NOT: load +; CHECK: ret + +define <4 x float> @vmul_optnone(<4 x float> %a, <4 x float> %b) #1 { +entry: + %a.addr = alloca <4 x float>, align 16 + %b.addr = alloca <4 x float>, align 16 + store <4 x float> %a, <4 x float>* %a.addr, align 16 + store <4 x float> %b, <4 x float>* %b.addr, align 16 + %0 = load <4 x float>* %a.addr, align 16 + %1 = load <4 x float>* %b.addr, align 16 + %mul = fmul <4 x float> %0, %1 + ret <4 x float> %mul +} + +; CHECK-LABEL: @vmul_optnone +; CHECK: alloca <4 x float> +; CHECK: alloca <4 x float> +; CHECK: store <4 x float> +; CHECK: store <4 x float> +; CHECK: load <4 x float> +; CHECK: load <4 x float> +; CHECK: fmul <4 x float> +; CHECK: ret diff --git a/test/Transforms/FunctionAttrs/optnone.ll b/test/Transforms/FunctionAttrs/optnone.ll new file mode 100644 index 000000000000..7694bfe13aa5 --- /dev/null +++ b/test/Transforms/FunctionAttrs/optnone.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -functionattrs -S | FileCheck %s + +@x = global i32 0 + +define void @test_opt(i8* %p) { +; CHECK-LABEL: @test_opt +; CHECK: (i8* nocapture readnone %p) #0 { + ret void +} + +define void @test_optnone(i8* %p) noinline optnone { +; CHECK-LABEL: @test_optnone +; CHECK: (i8* %p) #1 { + ret void +} + +declare i8 @strlen(i8*) noinline optnone +; CHECK-LABEL: @strlen +; CHECK: (i8*) #1 + +; CHECK-LABEL: attributes #0 +; CHECK: = { readnone } +; CHECK-LABEL: attributes #1 +; CHECK: = { noinline optnone } diff --git a/test/Transforms/GCOVProfiling/function-numbering.ll b/test/Transforms/GCOVProfiling/function-numbering.ll new file mode 100644 index 000000000000..487f4ca01a6b --- /dev/null +++ b/test/Transforms/GCOVProfiling/function-numbering.ll @@ -0,0 +1,56 @@ +; Test that GCOV instrumentation numbers functions correctly when some +; functions aren't emitted. + +; Inject metadata to set the .gcno file location +; RUN: echo '!14 = !{!"%/T/function-numbering.ll", !0}' > %t1 +; RUN: cat %s %t1 > %t2 + +; RUN: opt -insert-gcov-profiling -S < %t2 | FileCheck --check-prefix GCDA %s +; RUN: llvm-cov -n -dump %T/function-numbering.gcno 2>&1 | FileCheck --check-prefix GCNO %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.10.0" + +; GCDA: @[[FOO:[0-9]+]] = private unnamed_addr constant [4 x i8] c"foo\00" +; GCDA-NOT: @{{[0-9]+}} = private unnamed_addr constant .* c"bar\00" +; GCDA: @[[BAZ:[0-9]+]] = private unnamed_addr constant [4 x i8] c"baz\00" +; GCDA: define internal void @__llvm_gcov_writeout() +; GCDA: call void @llvm_gcda_emit_function(i32 0, i8* getelementptr inbounds ([4 x i8]* @[[FOO]] +; GCDA: call void @llvm_gcda_emit_function(i32 1, i8* getelementptr inbounds ([4 x i8]* @[[BAZ]] + +; GCNO: == foo (0) @ +; GCNO-NOT: == bar ({{[0-9]+}}) @ +; GCNO: == baz (1) @ + +define void @foo() { + ret void, !dbg !12 +} + +define void @bar() { + ; This function is referenced by the debug info, but no lines have locations. + ret void +} + +define void @baz() { + ret void, !dbg !13 +} + +!llvm.gcov = !{!14} +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!9, !10} +!llvm.ident = !{!11} + +!0 = !{!"0x11\0012\00clang version 3.6.0 \000\00\000\00\002", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [function-numbering.ll] [DW_LANG_C99] +!1 = !{!".../llvm/test/Transforms/GCOVProfiling/function-numbering.ll", !""} +!2 = !{} +!3 = !{!4, !7, !8} +!4 = !{!"0x2e\00foo\00foo\00\001\000\001\000\000\000\000\001", !1, !5, !6, null, void ()* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [/Users/bogner/build/llvm-debug//tmp/foo.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", null, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{!"0x2e\00bar\00bar\00\002\000\001\000\000\000\000\002", !1, !5, !6, null, void ()* @bar, null, null, !2} ; [ DW_TAG_subprogram ] [line 2] [def] [bar] +!8 = !{!"0x2e\00baz\00baz\00\003\000\001\000\000\000\000\003", !1, !5, !6, null, void ()* @baz, null, null, !2} ; [ DW_TAG_subprogram ] [line 3] [def] [baz] +!9 = !{i32 2, !"Dwarf Version", i32 2} +!10 = !{i32 2, !"Debug Info Version", i32 2} +!11 = !{!"clang version 3.6.0 "} +!12 = !MDLocation(line: 1, column: 13, scope: !4) +!13 = !MDLocation(line: 3, column: 13, scope: !8) diff --git a/test/Transforms/GCOVProfiling/global-ctor.ll b/test/Transforms/GCOVProfiling/global-ctor.ll index 722a0962ec57..9a9b7cecce7a 100644 --- a/test/Transforms/GCOVProfiling/global-ctor.ll +++ b/test/Transforms/GCOVProfiling/global-ctor.ll @@ -1,11 +1,9 @@ -; RUN: echo '!16 = metadata !{metadata !"%T/global-ctor.ll", metadata !0}' > %t1 +; RUN: echo '!16 = !{!"%/T/global-ctor.ll", !0}' > %t1 ; RUN: cat %s %t1 > %t2 ; RUN: opt -insert-gcov-profiling -disable-output < %t2 ; RUN: not grep '_GLOBAL__sub_I_global-ctor' %T/global-ctor.gcno ; RUN: rm %T/global-ctor.gcno -; REQUIRES: shell - @x = global i32 0, align 4 @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_global-ctor.ll, i8* null }] @@ -40,19 +38,19 @@ attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" " !llvm.gcov = !{!16} !llvm.ident = !{!12} -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.5.0 (trunk 210217)", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 2} ; [ DW_TAG_compile_unit ] [/home/nlewycky/<stdin>] [DW_LANG_C_plus_plus] -!1 = metadata !{metadata !"<stdin>", metadata !"/home/nlewycky"} -!2 = metadata !{} -!3 = metadata !{metadata !4, metadata !8} -!4 = metadata !{i32 786478, metadata !5, metadata !6, metadata !"__cxx_global_var_init", metadata !"__cxx_global_var_init", metadata !"", i32 2, metadata !7, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @__cxx_global_var_init, null, null, metadata !2, i32 2} ; [ DW_TAG_subprogram ] [line 2] [local] [def] [__cxx_global_var_init] -!5 = metadata !{metadata !"global-ctor.ll", metadata !"/home/nlewycky"} -!6 = metadata !{i32 786473, metadata !5} ; [ DW_TAG_file_type ] [/home/nlewycky/global-ctor.ll] -!7 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!8 = metadata !{i32 786478, metadata !1, metadata !9, metadata !"", metadata !"", metadata !"_GLOBAL__sub_I_global-ctor.ll", i32 0, metadata !7, i1 true, i1 true, i32 0, i32 0, null, i32 64, i1 false, void ()* @_GLOBAL__sub_I_global-ctor.ll, null, null, metadata !2, i32 0} ; [ DW_TAG_subprogram ] [line 0] [local] [def] -!9 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/home/nlewycky/<stdin>] -!10 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!11 = metadata !{i32 2, metadata !"Debug Info Version", i32 1} -!12 = metadata !{metadata !"clang version 3.5.0 (trunk 210217)"} -!13 = metadata !{i32 2, i32 0, metadata !4, null} -!14 = metadata !{i32 0, i32 0, metadata !15, null} -!15 = metadata !{i32 786443, metadata !5, metadata !8} ; [ DW_TAG_lexical_block ] [/home/nlewycky/global-ctor.ll] +!0 = !{!"0x11\004\00clang version 3.5.0 (trunk 210217)\000\00\000\00\002", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [/home/nlewycky/<stdin>] [DW_LANG_C_plus_plus] +!1 = !{!"<stdin>", !"/home/nlewycky"} +!2 = !{} +!3 = !{!4, !8} +!4 = !{!"0x2e\00__cxx_global_var_init\00__cxx_global_var_init\00\002\001\001\000\006\00256\000\002", !5, !6, !7, null, void ()* @__cxx_global_var_init, null, null, !2} ; [ DW_TAG_subprogram ] [line 2] [local] [def] [__cxx_global_var_init] +!5 = !{!"global-ctor.ll", !"/home/nlewycky"} +!6 = !{!"0x29", !5} ; [ DW_TAG_file_type ] [/home/nlewycky/global-ctor.ll] +!7 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!8 = !{!"0x2e\00\00\00_GLOBAL__sub_I_global-ctor.ll\000\001\001\000\006\0064\000\000", !1, !9, !7, null, void ()* @_GLOBAL__sub_I_global-ctor.ll, null, null, !2} ; [ DW_TAG_subprogram ] [line 0] [local] [def] +!9 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [/home/nlewycky/<stdin>] +!10 = !{i32 2, !"Dwarf Version", i32 4} +!11 = !{i32 2, !"Debug Info Version", i32 2} +!12 = !{!"clang version 3.5.0 (trunk 210217)"} +!13 = !MDLocation(line: 2, scope: !4) +!14 = !MDLocation(line: 0, scope: !15) +!15 = !{!"0xb\000", !5, !8} ; [ DW_TAG_lexical_block ] [/home/nlewycky/global-ctor.ll] diff --git a/test/Transforms/GCOVProfiling/linezero.ll b/test/Transforms/GCOVProfiling/linezero.ll index ba1c563c64ab..cf0fcd2cc820 100644 --- a/test/Transforms/GCOVProfiling/linezero.ll +++ b/test/Transforms/GCOVProfiling/linezero.ll @@ -1,7 +1,6 @@ -; RUN: sed -e 's|PATTERN|%T|g' < %s > %t1 +; RUN: sed -e 's|PATTERN|%/T|g' < %s > %t1 ; RUN: opt -insert-gcov-profiling -disable-output < %t1 ; RUN: rm %T/linezero.gcno %t1 -; REQUIRES: shell ; This is a crash test. @@ -20,17 +19,17 @@ entry: %__begin = alloca i8*, align 8 %__end = alloca i8*, align 8 %spec = alloca i8, align 1 - call void @llvm.dbg.declare(metadata !{%struct.vector** %__range}, metadata !27), !dbg !30 + call void @llvm.dbg.declare(metadata %struct.vector** %__range, metadata !27, metadata !{}), !dbg !30 br label %0 ; <label>:0 ; preds = %entry call void @_Z13TagFieldSpecsv(), !dbg !31 store %struct.vector* %ref.tmp, %struct.vector** %__range, align 8, !dbg !31 - call void @llvm.dbg.declare(metadata !{i8** %__begin}, metadata !32), !dbg !30 + call void @llvm.dbg.declare(metadata i8** %__begin, metadata !32, metadata !{}), !dbg !30 %1 = load %struct.vector** %__range, align 8, !dbg !31 %call = call i8* @_ZN6vector5beginEv(%struct.vector* %1), !dbg !31 store i8* %call, i8** %__begin, align 8, !dbg !31 - call void @llvm.dbg.declare(metadata !{i8** %__end}, metadata !33), !dbg !30 + call void @llvm.dbg.declare(metadata i8** %__end, metadata !33, metadata !{}), !dbg !30 %2 = load %struct.vector** %__range, align 8, !dbg !31 %call1 = call i8* @_ZN6vector3endEv(%struct.vector* %2), !dbg !31 store i8* %call1, i8** %__end, align 8, !dbg !31 @@ -43,7 +42,7 @@ for.cond: ; preds = %for.inc, %0 br i1 %cmp, label %for.body, label %for.end, !dbg !34 for.body: ; preds = %for.cond - call void @llvm.dbg.declare(metadata !{i8* %spec}, metadata !37), !dbg !31 + call void @llvm.dbg.declare(metadata i8* %spec, metadata !37, metadata !{}), !dbg !31 %5 = load i8** %__begin, align 8, !dbg !38 %6 = load i8* %5, align 1, !dbg !38 store i8 %6, i8* %spec, align 1, !dbg !38 @@ -65,7 +64,7 @@ return: ; No predecessors! } ; Function Attrs: nounwind readnone -declare void @llvm.dbg.declare(metadata, metadata) #1 +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 declare void @_Z13TagFieldSpecsv() #2 @@ -95,49 +94,49 @@ attributes #3 = { noreturn nounwind } !llvm.gcov = !{!25} !llvm.ident = !{!26} -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.5.0 (trunk 209871)", i1 false, metadata !"", i32 0, metadata !2, metadata !3, metadata !14, metadata !2, metadata !2, metadata !"", i32 1} ; [ DW_TAG_compile_unit ] [<stdin>] [DW_LANG_C_plus_plus] -!1 = metadata !{metadata !"<stdin>", metadata !"PATTERN"} -!2 = metadata !{} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786451, metadata !5, null, metadata !"vector", i32 21, i64 8, i64 8, i32 0, i32 0, null, metadata !6, i32 0, null, null, metadata !"_ZTS6vector"} ; [ DW_TAG_structure_type ] [vector] [line 21, size 8, align 8, offset 0] [def] [from ] -!5 = metadata !{metadata !"linezero.cc", metadata !"PATTERN"} -!6 = metadata !{metadata !7, metadata !13} -!7 = metadata !{i32 786478, metadata !5, metadata !"_ZTS6vector", metadata !"begin", metadata !"begin", metadata !"_ZN6vector5beginEv", i32 25, metadata !8, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 false, null, null, i32 0, null, i32 25} ; [ DW_TAG_subprogram ] [line 25] [begin] -!8 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !9, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!9 = metadata !{metadata !10, metadata !12} -!10 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !11} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from char] -!11 = metadata !{i32 786468, null, null, metadata !"char", i32 0, i64 8, i64 8, i64 0, i32 0, i32 6} ; [ DW_TAG_base_type ] [char] [line 0, size 8, align 8, offset 0, enc DW_ATE_signed_char] -!12 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 1088, metadata !"_ZTS6vector"} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [artificial] [from _ZTS6vector] -!13 = metadata !{i32 786478, metadata !5, metadata !"_ZTS6vector", metadata !"end", metadata !"end", metadata !"_ZN6vector3endEv", i32 26, metadata !8, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 false, null, null, i32 0, null, i32 26} ; [ DW_TAG_subprogram ] [line 26] [end] -!14 = metadata !{metadata !15, metadata !20} -!15 = metadata !{i32 786478, metadata !5, metadata !16, metadata !"test", metadata !"test", metadata !"_Z4testv", i32 50, metadata !17, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 ()* @_Z4testv, null, null, metadata !2, i32 50} ; [ DW_TAG_subprogram ] [line 50] [def] [test] -!16 = metadata !{i32 786473, metadata !5} ; [ DW_TAG_file_type ] [./linezero.cc] -!17 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !18, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!18 = metadata !{metadata !19} -!19 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] -!20 = metadata !{i32 786478, metadata !5, metadata !16, metadata !"f1", metadata !"f1", metadata !"_Z2f1v", i32 54, metadata !21, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @_Z2f1v, null, null, metadata !2, i32 54} ; [ DW_TAG_subprogram ] [line 54] [def] [f1] -!21 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !22, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!22 = metadata !{null} -!23 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!24 = metadata !{i32 2, metadata !"Debug Info Version", i32 1} -!25 = metadata !{metadata !"PATTERN/linezero.o", metadata !0} -!26 = metadata !{metadata !"clang version 3.5.0 (trunk 209871)"} -!27 = metadata !{i32 786688, metadata !28, metadata !"__range", null, i32 0, metadata !29, i32 64, i32 0} ; [ DW_TAG_auto_variable ] [__range] [line 0] -!28 = metadata !{i32 786443, metadata !5, metadata !15, i32 51, i32 0, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [./linezero.cc] -!29 = metadata !{i32 786498, null, null, null, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !"_ZTS6vector"} ; [ DW_TAG_rvalue_reference_type ] [line 0, size 0, align 0, offset 0] [from _ZTS6vector] -!30 = metadata !{i32 0, i32 0, metadata !28, null} -!31 = metadata !{i32 51, i32 0, metadata !28, null} -!32 = metadata !{i32 786688, metadata !28, metadata !"__begin", null, i32 0, metadata !10, i32 64, i32 0} ; [ DW_TAG_auto_variable ] [__begin] [line 0] -!33 = metadata !{i32 786688, metadata !28, metadata !"__end", null, i32 0, metadata !10, i32 64, i32 0} ; [ DW_TAG_auto_variable ] [__end] [line 0] -!34 = metadata !{i32 51, i32 0, metadata !35, null} -!35 = metadata !{i32 786443, metadata !5, metadata !36, i32 51, i32 0, i32 5, i32 5} ; [ DW_TAG_lexical_block ] [./linezero.cc] -!36 = metadata !{i32 786443, metadata !5, metadata !28, i32 51, i32 0, i32 1, i32 1} ; [ DW_TAG_lexical_block ] [./linezero.cc] -!37 = metadata !{i32 786688, metadata !28, metadata !"spec", metadata !16, i32 51, metadata !11, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [spec] [line 51] -!38 = metadata !{i32 51, i32 0, metadata !39, null} -!39 = metadata !{i32 786443, metadata !5, metadata !28, i32 51, i32 0, i32 2, i32 2} ; [ DW_TAG_lexical_block ] [./linezero.cc] -!40 = metadata !{i32 51, i32 0, metadata !41, null} -!41 = metadata !{i32 786443, metadata !5, metadata !28, i32 51, i32 0, i32 4, i32 4} ; [ DW_TAG_lexical_block ] [./linezero.cc] -!42 = metadata !{i32 51, i32 0, metadata !43, null} -!43 = metadata !{i32 786443, metadata !5, metadata !28, i32 51, i32 0, i32 3, i32 3} ; [ DW_TAG_lexical_block ] [./linezero.cc] -!44 = metadata !{i32 52, i32 0, metadata !15, null} -!45 = metadata !{i32 54, i32 0, metadata !20, null} +!0 = !{!"0x11\004\00clang version 3.5.0 (trunk 209871)\000\00\000\00\001", !1, !2, !3, !14, !2, !2} ; [ DW_TAG_compile_unit ] [<stdin>] [DW_LANG_C_plus_plus] +!1 = !{!"<stdin>", !"PATTERN"} +!2 = !{} +!3 = !{!4} +!4 = !{!"0x13\00vector\0021\008\008\000\000\000", !5, null, null, !6, null, null, !"_ZTS6vector"} ; [ DW_TAG_structure_type ] [vector] [line 21, size 8, align 8, offset 0] [def] [from ] +!5 = !{!"linezero.cc", !"PATTERN"} +!6 = !{!7, !13} +!7 = !{!"0x2e\00begin\00begin\00_ZN6vector5beginEv\0025\000\000\000\006\00256\000\0025", !5, !"_ZTS6vector", !8, null, null, null, i32 0, null} ; [ DW_TAG_subprogram ] [line 25] [begin] +!8 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !9, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!9 = !{!10, !12} +!10 = !{!"0xf\00\000\0064\0064\000\000", null, null, !11} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from char] +!11 = !{!"0x24\00char\000\008\008\000\000\006", null, null} ; [ DW_TAG_base_type ] [char] [line 0, size 8, align 8, offset 0, enc DW_ATE_signed_char] +!12 = !{!"0xf\00\000\0064\0064\000\001088", null, null, !"_ZTS6vector"} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [artificial] [from _ZTS6vector] +!13 = !{!"0x2e\00end\00end\00_ZN6vector3endEv\0026\000\000\000\006\00256\000\0026", !5, !"_ZTS6vector", !8, null, null, null, i32 0, null} ; [ DW_TAG_subprogram ] [line 26] [end] +!14 = !{!15, !20} +!15 = !{!"0x2e\00test\00test\00_Z4testv\0050\000\001\000\006\00256\000\0050", !5, !16, !17, null, i32 ()* @_Z4testv, null, null, !2} ; [ DW_TAG_subprogram ] [line 50] [def] [test] +!16 = !{!"0x29", !5} ; [ DW_TAG_file_type ] [./linezero.cc] +!17 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !18, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!18 = !{!19} +!19 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!20 = !{!"0x2e\00f1\00f1\00_Z2f1v\0054\000\001\000\006\00256\000\0054", !5, !16, !21, null, void ()* @_Z2f1v, null, null, !2} ; [ DW_TAG_subprogram ] [line 54] [def] [f1] +!21 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !22, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!22 = !{null} +!23 = !{i32 2, !"Dwarf Version", i32 4} +!24 = !{i32 2, !"Debug Info Version", i32 2} +!25 = !{!"PATTERN/linezero.o", !0} +!26 = !{!"clang version 3.5.0 (trunk 209871)"} +!27 = !{!"0x100\00__range\000\0064", !28, null, !29} ; [ DW_TAG_auto_variable ] [__range] [line 0] +!28 = !{!"0xb\0051\000\000", !5, !15} ; [ DW_TAG_lexical_block ] [./linezero.cc] +!29 = !{!"0x42\00\000\000\000\000\000", null, null, !"_ZTS6vector"} ; [ DW_TAG_rvalue_reference_type ] [line 0, size 0, align 0, offset 0] [from _ZTS6vector] +!30 = !MDLocation(line: 0, scope: !28) +!31 = !MDLocation(line: 51, scope: !28) +!32 = !{!"0x100\00__begin\000\0064", !28, null, !10} ; [ DW_TAG_auto_variable ] [__begin] [line 0] +!33 = !{!"0x100\00__end\000\0064", !28, null, !10} ; [ DW_TAG_auto_variable ] [__end] [line 0] +!34 = !MDLocation(line: 51, scope: !35) +!35 = !{!"0xb\0051\000\005", !5, !36} ; [ DW_TAG_lexical_block ] [./linezero.cc] +!36 = !{!"0xb\0051\000\001", !5, !28} ; [ DW_TAG_lexical_block ] [./linezero.cc] +!37 = !{!"0x100\00spec\0051\000", !28, !16, !11} ; [ DW_TAG_auto_variable ] [spec] [line 51] +!38 = !MDLocation(line: 51, scope: !39) +!39 = !{!"0xb\0051\000\002", !5, !28} ; [ DW_TAG_lexical_block ] [./linezero.cc] +!40 = !MDLocation(line: 51, scope: !41) +!41 = !{!"0xb\0051\000\004", !5, !28} ; [ DW_TAG_lexical_block ] [./linezero.cc] +!42 = !MDLocation(line: 51, scope: !43) +!43 = !{!"0xb\0051\000\003", !5, !28} ; [ DW_TAG_lexical_block ] [./linezero.cc] +!44 = !MDLocation(line: 52, scope: !15) +!45 = !MDLocation(line: 54, scope: !20) diff --git a/test/Transforms/GCOVProfiling/linkagename.ll b/test/Transforms/GCOVProfiling/linkagename.ll index ed3a5bd93ada..c30d4a61ced4 100644 --- a/test/Transforms/GCOVProfiling/linkagename.ll +++ b/test/Transforms/GCOVProfiling/linkagename.ll @@ -1,11 +1,9 @@ -; RUN: echo '!9 = metadata !{metadata !"%T/linkagename.ll", metadata !0}' > %t1 +; RUN: echo '!9 = !{!"%/T/linkagename.ll", !0}' > %t1 ; RUN: cat %s %t1 > %t2 ; RUN: opt -insert-gcov-profiling -disable-output < %t2 ; RUN: grep _Z3foov %T/linkagename.gcno ; RUN: rm %T/linkagename.gcno -; REQUIRES: shell - define void @_Z3foov() { entry: ret void, !dbg !8 @@ -15,15 +13,15 @@ entry: !llvm.module.flags = !{!10} !llvm.gcov = !{!9} -!0 = metadata !{i32 786449, metadata !2, i32 4, metadata !"clang version 3.3 (trunk 177323)", i1 false, metadata !"", i32 0, metadata !3, metadata !3, metadata !4, metadata !3, metadata !3, metadata !""} ; [ DW_TAG_compile_unit ] [/home/nlewycky/hello.cc] [DW_LANG_C_plus_plus] -!1 = metadata !{i32 786473, metadata !2} ; [ DW_TAG_file_type ] [/home/nlewycky/hello.cc] -!2 = metadata !{metadata !"hello.cc", metadata !"/home/nlewycky"} -!3 = metadata !{i32 0} -!4 = metadata !{metadata !5} -!5 = metadata !{i32 786478, metadata !1, metadata !1, metadata !"foo", metadata !"foo", metadata !"_Z3foov", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @_Z3foov, null, null, metadata !3, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] -!6 = metadata !{i32 786453, i32 0, null, i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{null} -!8 = metadata !{i32 1, i32 0, metadata !5, null} +!0 = !{!"0x11\004\00clang version 3.3 (trunk 177323)\000\00\000\00\000", !2, !3, !3, !4, !3, !3} ; [ DW_TAG_compile_unit ] [/home/nlewycky/hello.cc] [DW_LANG_C_plus_plus] +!1 = !{!"0x29", !2} ; [ DW_TAG_file_type ] [/home/nlewycky/hello.cc] +!2 = !{!"hello.cc", !"/home/nlewycky"} +!3 = !{i32 0} +!4 = !{!5} +!5 = !{!"0x2e\00foo\00foo\00_Z3foov\001\000\001\000\006\00256\000\001", !1, !1, !6, null, void ()* @_Z3foov, null, null, !3} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !7, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{null} +!8 = !MDLocation(line: 1, scope: !5) -!10 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!10 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/GCOVProfiling/return-block.ll b/test/Transforms/GCOVProfiling/return-block.ll new file mode 100644 index 000000000000..f0be3d21aeb2 --- /dev/null +++ b/test/Transforms/GCOVProfiling/return-block.ll @@ -0,0 +1,66 @@ +; Inject metadata to set the .gcno file location +; RUN: echo '!19 = !{!"%/T/return-block.ll", !0}' > %t1 +; RUN: cat %s %t1 > %t2 +; RUN: opt -insert-gcov-profiling -disable-output %t2 +; RUN: llvm-cov gcov -n -dump %T/return-block.gcno 2>&1 | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@A = common global i32 0, align 4 + +; Function Attrs: nounwind uwtable +define void @test() #0 { +entry: + tail call void (...)* @f() #2, !dbg !14 + %0 = load i32* @A, align 4, !dbg !15 + %tobool = icmp eq i32 %0, 0, !dbg !15 + br i1 %tobool, label %if.end, label %if.then, !dbg !15 + +if.then: ; preds = %entry + tail call void (...)* @g() #2, !dbg !16 + br label %if.end, !dbg !16 + +if.end: ; preds = %entry, %if.then + ret void, !dbg !18 +} + +declare void @f(...) #1 + +declare void @g(...) #1 + +attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind } + +!llvm.gcov = !{!19} +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!11, !12} +!llvm.ident = !{!13} + +!0 = !{!"0x11\0012\00clang version 3.6.0 (trunk 223182)\001\00\000\00\001", !1, !2, !2, !3, !8, !2} ; [ DW_TAG_compile_unit ] [return-block.c] [DW_LANG_C99] +!1 = !{!".../llvm/test/Transforms/GCOVProfiling/return-block.ll", !""} +!2 = !{} +!3 = !{!4} +!4 = !{!"0x2e\00test\00test\00\005\000\001\000\000\000\001\005", !1, !5, !6, null, void ()* @test, null, null, !2} ; [ DW_TAG_subprogram ] [line 5] [def] [test] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [return-block.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", null, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{null} +!8 = !{!9} +!9 = !{!"0x34\00A\00A\00\003\000\001", null, !5, !10, i32* @A, null} ; [ DW_TAG_variable ] [A] [line 3] [def] +!10 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!11 = !{i32 2, !"Dwarf Version", i32 4} +!12 = !{i32 2, !"Debug Info Version", i32 2} +!13 = !{!"clang version 3.6.0 (trunk 223182)"} +!14 = !MDLocation(line: 6, column: 3, scope: !4) +!15 = !MDLocation(line: 7, column: 7, scope: !4) +!16 = !MDLocation(line: 8, column: 5, scope: !17) +!17 = !{!"0xb\007\007\000", !1, !4} ; [ DW_TAG_lexical_block ] [return-block.c] +!18 = !MDLocation(line: 9, column: 1, scope: !4) + +; There should be no destination edges for block 1. +; CHECK: Block : 0 Counter : 0 +; CHECK-NEXT: Destination Edges : 2 (0), +; CHECK-NEXT: Block : 1 Counter : 0 +; CHECK-NEXT: Source Edges : 4 (0), +; CHECK-NEXT: Block : 2 Counter : 0 diff --git a/test/Transforms/GCOVProfiling/version.ll b/test/Transforms/GCOVProfiling/version.ll index 04f3f992b836..9436bd657da3 100644 --- a/test/Transforms/GCOVProfiling/version.ll +++ b/test/Transforms/GCOVProfiling/version.ll @@ -1,32 +1,30 @@ -; RUN: echo '!9 = metadata !{metadata !"%T/version.ll", metadata !0}' > %t1 +; RUN: echo '!9 = !{!"%/T/version.ll", !0}' > %t1 ; RUN: cat %s %t1 > %t2 ; RUN: opt -insert-gcov-profiling -disable-output < %t2 -; RUN: head -c8 %T/version.gcno | grep '^oncg\*204' +; RUN: head -c8 %T/version.gcno | grep '^oncg.204' ; RUN: rm %T/version.gcno ; RUN: not opt -insert-gcov-profiling -default-gcov-version=asdfasdf -disable-output < %t2 ; RUN: opt -insert-gcov-profiling -default-gcov-version=407* -disable-output < %t2 -; RUN: head -c8 %T/version.gcno | grep '^oncg\*704' +; RUN: head -c8 %T/version.gcno | grep '^oncg.704' ; RUN: rm %T/version.gcno define void @test() { ret void, !dbg !8 } -; REQUIRES: shell - !llvm.gcov = !{!9} !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!12} -!0 = metadata !{i32 786449, metadata !11, i32 4, metadata !"clang version 3.3 (trunk 176994)", i1 false, metadata !"", i32 0, metadata !3, metadata !3, metadata !4, metadata !3, null, metadata !""} ; [ DW_TAG_compile_unit ] [./version] [DW_LANG_C_plus_plus] -!2 = metadata !{i32 786473, metadata !11} ; [ DW_TAG_file_type ] -!3 = metadata !{i32 0} -!4 = metadata !{metadata !5} -!5 = metadata !{i32 786478, metadata !10, metadata !6, metadata !"test", metadata !"test", metadata !"", i32 1, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @test, null, null, metadata !3, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [test] -!6 = metadata !{i32 786473, metadata !10} ; [ DW_TAG_file_type ] -!7 = metadata !{i32 786453, i32 0, null, i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !3, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!8 = metadata !{i32 1, i32 0, metadata !5, null} +!0 = !{!"0x11\004\00clang version 3.3 (trunk 176994)\000\00\000\00\000", !11, !3, !3, !4, !3, null} ; [ DW_TAG_compile_unit ] [./version] [DW_LANG_C_plus_plus] +!2 = !{!"0x29", !11} ; [ DW_TAG_file_type ] +!3 = !{i32 0} +!4 = !{!5} +!5 = !{!"0x2e\00test\00test\00\001\000\001\000\006\00256\000\001", !10, !6, !7, null, void ()* @test, null, null, !3} ; [ DW_TAG_subprogram ] [line 1] [def] [test] +!6 = !{!"0x29", !10} ; [ DW_TAG_file_type ] +!7 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !3, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!8 = !MDLocation(line: 1, scope: !5) ;; !9 is added through the echo line at the top. -!10 = metadata !{metadata !"<stdin>", metadata !"."} -!11 = metadata !{metadata !"version", metadata !"/usr/local/google/home/nlewycky"} -!12 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!10 = !{!"<stdin>", !"."} +!11 = !{!"version", !"/usr/local/google/home/nlewycky"} +!12 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/GVN/2009-03-10-PREOnVoid.ll b/test/Transforms/GVN/2009-03-10-PREOnVoid.ll index fd31fce59a84..fdf17e0b46df 100644 --- a/test/Transforms/GVN/2009-03-10-PREOnVoid.ll +++ b/test/Transforms/GVN/2009-03-10-PREOnVoid.ll @@ -17,20 +17,20 @@ target triple = "i386-pc-linux-gnu" %"struct.std::pair<std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,bool>" = type { %"struct.std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >", i8 } %"struct.std::pair<void* const,void*>" = type { i8*, i8* } -@_ZL20__gthrw_pthread_oncePiPFvvE = alias weak i32 (i32*, void ()*)* @pthread_once ; <i32 (i32*, void ()*)*> [#uses=0] -@_ZL27__gthrw_pthread_getspecificj = alias weak i8* (i32)* @pthread_getspecific ; <i8* (i32)*> [#uses=0] -@_ZL27__gthrw_pthread_setspecificjPKv = alias weak i32 (i32, i8*)* @pthread_setspecific ; <i32 (i32, i8*)*> [#uses=0] -@_ZL22__gthrw_pthread_createPmPK16__pthread_attr_sPFPvS3_ES3_ = alias weak i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*)* @pthread_create ; <i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*)*> [#uses=0] -@_ZL22__gthrw_pthread_cancelm = alias weak i32 (i32)* @pthread_cancel ; <i32 (i32)*> [#uses=0] -@_ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t = alias weak i32 (%struct.pthread_mutex_t*)* @pthread_mutex_lock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0] -@_ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t = alias weak i32 (%struct.pthread_mutex_t*)* @pthread_mutex_trylock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0] -@_ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t = alias weak i32 (%struct.pthread_mutex_t*)* @pthread_mutex_unlock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0] -@_ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t = alias weak i32 (%struct.pthread_mutex_t*, %struct.__sched_param*)* @pthread_mutex_init ; <i32 (%struct.pthread_mutex_t*, %struct.__sched_param*)*> [#uses=0] -@_ZL26__gthrw_pthread_key_createPjPFvPvE = alias weak i32 (i32*, void (i8*)*)* @pthread_key_create ; <i32 (i32*, void (i8*)*)*> [#uses=0] -@_ZL26__gthrw_pthread_key_deletej = alias weak i32 (i32)* @pthread_key_delete ; <i32 (i32)*> [#uses=0] -@_ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t = alias weak i32 (%struct.__sched_param*)* @pthread_mutexattr_init ; <i32 (%struct.__sched_param*)*> [#uses=0] -@_ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti = alias weak i32 (%struct.__sched_param*, i32)* @pthread_mutexattr_settype ; <i32 (%struct.__sched_param*, i32)*> [#uses=0] -@_ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t = alias weak i32 (%struct.__sched_param*)* @pthread_mutexattr_destroy ; <i32 (%struct.__sched_param*)*> [#uses=0] +@_ZL20__gthrw_pthread_oncePiPFvvE = weak alias i32 (i32*, void ()*)* @pthread_once ; <i32 (i32*, void ()*)*> [#uses=0] +@_ZL27__gthrw_pthread_getspecificj = weak alias i8* (i32)* @pthread_getspecific ; <i8* (i32)*> [#uses=0] +@_ZL27__gthrw_pthread_setspecificjPKv = weak alias i32 (i32, i8*)* @pthread_setspecific ; <i32 (i32, i8*)*> [#uses=0] +@_ZL22__gthrw_pthread_createPmPK16__pthread_attr_sPFPvS3_ES3_ = weak alias i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*)* @pthread_create ; <i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*)*> [#uses=0] +@_ZL22__gthrw_pthread_cancelm = weak alias i32 (i32)* @pthread_cancel ; <i32 (i32)*> [#uses=0] +@_ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t = weak alias i32 (%struct.pthread_mutex_t*)* @pthread_mutex_lock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0] +@_ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t = weak alias i32 (%struct.pthread_mutex_t*)* @pthread_mutex_trylock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0] +@_ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t = weak alias i32 (%struct.pthread_mutex_t*)* @pthread_mutex_unlock ; <i32 (%struct.pthread_mutex_t*)*> [#uses=0] +@_ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t = weak alias i32 (%struct.pthread_mutex_t*, %struct.__sched_param*)* @pthread_mutex_init ; <i32 (%struct.pthread_mutex_t*, %struct.__sched_param*)*> [#uses=0] +@_ZL26__gthrw_pthread_key_createPjPFvPvE = weak alias i32 (i32*, void (i8*)*)* @pthread_key_create ; <i32 (i32*, void (i8*)*)*> [#uses=0] +@_ZL26__gthrw_pthread_key_deletej = weak alias i32 (i32)* @pthread_key_delete ; <i32 (i32)*> [#uses=0] +@_ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t = weak alias i32 (%struct.__sched_param*)* @pthread_mutexattr_init ; <i32 (%struct.__sched_param*)*> [#uses=0] +@_ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti = weak alias i32 (%struct.__sched_param*, i32)* @pthread_mutexattr_settype ; <i32 (%struct.__sched_param*, i32)*> [#uses=0] +@_ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t = weak alias i32 (%struct.__sched_param*)* @pthread_mutexattr_destroy ; <i32 (%struct.__sched_param*)*> [#uses=0] declare fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind readnone diff --git a/test/Transforms/GVN/atomic.ll b/test/Transforms/GVN/atomic.ll index 094e22bd07e1..8c13d209c53a 100644 --- a/test/Transforms/GVN/atomic.ll +++ b/test/Transforms/GVN/atomic.ll @@ -8,7 +8,7 @@ target triple = "x86_64-apple-macosx10.7.0" ; GVN across unordered store (allowed) define i32 @test1() nounwind uwtable ssp { -; CHECK: test1 +; CHECK-LABEL: test1 ; CHECK: add i32 %x, %x entry: %x = load i32* @y @@ -18,10 +18,10 @@ entry: ret i32 %z } -; GVN across seq_cst store (allowed in theory; not implemented ATM) +; GVN across seq_cst store (allowed) define i32 @test2() nounwind uwtable ssp { -; CHECK: test2 -; CHECK: add i32 %x, %y +; CHECK-LABEL: test2 +; CHECK: add i32 %x, %x entry: %x = load i32* @y store atomic i32 %x, i32* @x seq_cst, align 4 @@ -32,7 +32,7 @@ entry: ; GVN across unordered load (allowed) define i32 @test3() nounwind uwtable ssp { -; CHECK: test3 +; CHECK-LABEL: test3 ; CHECK: add i32 %x, %x entry: %x = load i32* @y @@ -43,11 +43,11 @@ entry: ret i32 %b } -; GVN across acquire load (load after atomic load must not be removed) +; GVN across acquire load (allowed as the original load was not atomic) define i32 @test4() nounwind uwtable ssp { -; CHECK: test4 +; CHECK-LABEL: test4 ; CHECK: load atomic i32* @x -; CHECK: load i32* @y +; CHECK-NOT: load i32* @y entry: %x = load i32* @y %y = load atomic i32* @x seq_cst, align 4 @@ -59,7 +59,7 @@ entry: ; GVN load to unordered load (allowed) define i32 @test5() nounwind uwtable ssp { -; CHECK: test5 +; CHECK-LABEL: test5 ; CHECK: add i32 %x, %x entry: %x = load atomic i32* @x unordered, align 4 @@ -70,7 +70,7 @@ entry: ; GVN unordered load to load (unordered load must not be removed) define i32 @test6() nounwind uwtable ssp { -; CHECK: test6 +; CHECK-LABEL: test6 ; CHECK: load atomic i32* @x unordered entry: %x = load i32* @x @@ -78,3 +78,54 @@ entry: %x3 = add i32 %x, %x2 ret i32 %x3 } + +; GVN across release-acquire pair (forbidden) +define i32 @test7() nounwind uwtable ssp { +; CHECK-LABEL: test7 +; CHECK: add i32 %x, %y +entry: + %x = load i32* @y + store atomic i32 %x, i32* @x release, align 4 + %w = load atomic i32* @x acquire, align 4 + %y = load i32* @y + %z = add i32 %x, %y + ret i32 %z +} + +; GVN across acquire-release pair (allowed) +define i32 @test8() nounwind uwtable ssp { +; CHECK-LABEL: test8 +; CHECK: add i32 %x, %x +entry: + %x = load i32* @y + %w = load atomic i32* @x acquire, align 4 + store atomic i32 %x, i32* @x release, align 4 + %y = load i32* @y + %z = add i32 %x, %y + ret i32 %z +} + +; GVN across monotonic store (allowed) +define i32 @test9() nounwind uwtable ssp { +; CHECK-LABEL: test9 +; CHECK: add i32 %x, %x +entry: + %x = load i32* @y + store atomic i32 %x, i32* @x monotonic, align 4 + %y = load i32* @y + %z = add i32 %x, %y + ret i32 %z +} + +; GVN of an unordered across monotonic load (not allowed) +define i32 @test10() nounwind uwtable ssp { +; CHECK-LABEL: test10 +; CHECK: add i32 %x, %y +entry: + %x = load atomic i32* @y unordered, align 4 + %clobber = load atomic i32* @x monotonic, align 4 + %y = load atomic i32* @y monotonic, align 4 + %z = add i32 %x, %y + ret i32 %z +} + diff --git a/test/Transforms/GVN/cond_br2.ll b/test/Transforms/GVN/cond_br2.ll index 27e6f75de271..a7ca2190563b 100644 --- a/test/Transforms/GVN/cond_br2.ll +++ b/test/Transforms/GVN/cond_br2.ll @@ -132,9 +132,9 @@ attributes #1 = { nounwind } attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #3 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -!0 = metadata !{metadata !"any pointer", metadata !1} -!1 = metadata !{metadata !"omnipotent char", metadata !2} -!2 = metadata !{metadata !"Simple C/C++ TBAA"} -!3 = metadata !{metadata !"int", metadata !1} -!4 = metadata !{metadata !0, metadata !0, i64 0} -!5 = metadata !{metadata !3, metadata !3, i64 0} +!0 = !{!"any pointer", !1} +!1 = !{!"omnipotent char", !2} +!2 = !{!"Simple C/C++ TBAA"} +!3 = !{!"int", !1} +!4 = !{!0, !0, i64 0} +!5 = !{!3, !3, i64 0} diff --git a/test/Transforms/GVN/condprop.ll b/test/Transforms/GVN/condprop.ll index 708e4b23cb54..845f88e15895 100644 --- a/test/Transforms/GVN/condprop.ll +++ b/test/Transforms/GVN/condprop.ll @@ -144,6 +144,22 @@ different: ret i1 %cmp3 } +; CHECK-LABEL: @test6_fp( +define i1 @test6_fp(float %x, float %y) { + %cmp2 = fcmp une float %x, %y + %cmp = fcmp oeq float %x, %y + %cmp3 = fcmp oeq float %x, %y + br i1 %cmp, label %same, label %different + +same: +; CHECK: ret i1 false + ret i1 %cmp2 + +different: +; CHECK: ret i1 false + ret i1 %cmp3 +} + ; CHECK-LABEL: @test7( define i1 @test7(i32 %x, i32 %y) { %cmp = icmp sgt i32 %x, %y @@ -160,6 +176,22 @@ different: ret i1 %cmp3 } +; CHECK-LABEL: @test7_fp( +define i1 @test7_fp(float %x, float %y) { + %cmp = fcmp ogt float %x, %y + br i1 %cmp, label %same, label %different + +same: + %cmp2 = fcmp ule float %x, %y +; CHECK: ret i1 false + ret i1 %cmp2 + +different: + %cmp3 = fcmp ogt float %x, %y +; CHECK: ret i1 false + ret i1 %cmp3 +} + ; CHECK-LABEL: @test8( define i1 @test8(i32 %x, i32 %y) { %cmp2 = icmp sle i32 %x, %y @@ -176,6 +208,22 @@ different: ret i1 %cmp3 } +; CHECK-LABEL: @test8_fp( +define i1 @test8_fp(float %x, float %y) { + %cmp2 = fcmp ule float %x, %y + %cmp = fcmp ogt float %x, %y + %cmp3 = fcmp ogt float %x, %y + br i1 %cmp, label %same, label %different + +same: +; CHECK: ret i1 false + ret i1 %cmp2 + +different: +; CHECK: ret i1 false + ret i1 %cmp3 +} + ; PR1768 ; CHECK-LABEL: @test9( define i32 @test9(i32 %i, i32 %j) { diff --git a/test/Transforms/GVN/edge.ll b/test/Transforms/GVN/edge.ll index 646e10c0cdfb..1dc285ec3d7c 100644 --- a/test/Transforms/GVN/edge.ll +++ b/test/Transforms/GVN/edge.ll @@ -58,3 +58,38 @@ bb2: ; CHECK: call void @g(i1 %y) ret void } + +define double @fcmp_oeq(double %x, double %y) { +entry: + %cmp = fcmp oeq double %y, 2.0 + br i1 %cmp, label %if, label %return + +if: + %div = fdiv double %x, %y + br label %return + +return: + %retval.0 = phi double [ %div, %if ], [ %x, %entry ] + ret double %retval.0 + +; CHECK-LABEL: define double @fcmp_oeq( +; CHECK: %div = fdiv double %x, 2.000000e+00 +} + +define double @fcmp_une(double %x, double %y) { +entry: + %cmp = fcmp une double %y, 2.0 + br i1 %cmp, label %return, label %else + +else: + %div = fdiv double %x, %y + br label %return + +return: + %retval.0 = phi double [ %div, %else ], [ %x, %entry ] + ret double %retval.0 + +; CHECK-LABEL: define double @fcmp_une( +; CHECK: %div = fdiv double %x, 2.000000e+00 +} + diff --git a/test/Transforms/GVN/fpmath.ll b/test/Transforms/GVN/fpmath.ll index 403df5c9008a..d164fb5e704e 100644 --- a/test/Transforms/GVN/fpmath.ll +++ b/test/Transforms/GVN/fpmath.ll @@ -41,5 +41,5 @@ define double @test4(double %x, double %y) { ret double %foo } -!0 = metadata !{ float 5.0 } -!1 = metadata !{ float 2.5 } +!0 = !{ float 5.0 } +!1 = !{ float 2.5 } diff --git a/test/Transforms/GVN/invariant-load.ll b/test/Transforms/GVN/invariant-load.ll index 80e2226b5fae..2f9f2a6100fb 100644 --- a/test/Transforms/GVN/invariant-load.ll +++ b/test/Transforms/GVN/invariant-load.ll @@ -27,5 +27,5 @@ entry: ret i32 %add } -!0 = metadata !{ } +!0 = !{ } diff --git a/test/Transforms/GVN/load-from-unreachable-predecessor.ll b/test/Transforms/GVN/load-from-unreachable-predecessor.ll new file mode 100644 index 000000000000..b676d958aa4a --- /dev/null +++ b/test/Transforms/GVN/load-from-unreachable-predecessor.ll @@ -0,0 +1,20 @@ +; RUN: opt -gvn -S < %s | FileCheck %s + +; Check that an unreachable predecessor to a PHI node doesn't cause a crash. +; PR21625. + +define i32 @f(i32** %f) { +; CHECK: bb0: +; Load should be removed, since it's ignored. +; CHECK-NEXT: br label +bb0: + %bar = load i32** %f + br label %bb2 +bb1: + %zed = load i32** %f + br i1 false, label %bb1, label %bb2 +bb2: + %foo = phi i32* [ null, %bb0 ], [ %zed, %bb1 ] + %storemerge = load i32* %foo + ret i32 %storemerge +} diff --git a/test/Transforms/GVN/load-pre-nonlocal.ll b/test/Transforms/GVN/load-pre-nonlocal.ll index 7bac1b78e6a2..ae508b96cf59 100644 --- a/test/Transforms/GVN/load-pre-nonlocal.ll +++ b/test/Transforms/GVN/load-pre-nonlocal.ll @@ -79,9 +79,9 @@ if.end: ret i32 %add1 } -!1 = metadata !{metadata !2, metadata !2, i64 0} -!2 = metadata !{metadata !"any pointer", metadata !3, i64 0} -!3 = metadata !{metadata !"omnipotent char", metadata !4, i64 0} -!4 = metadata !{metadata !"Simple C/C++ TBAA"} -!5 = metadata !{metadata !6, metadata !6, i64 0} -!6 = metadata !{metadata !"int", metadata !3, i64 0} +!1 = !{!2, !2, i64 0} +!2 = !{!"any pointer", !3, i64 0} +!3 = !{!"omnipotent char", !4, i64 0} +!4 = !{!"Simple C/C++ TBAA"} +!5 = !{!6, !6, i64 0} +!6 = !{!"int", !3, i64 0} diff --git a/test/Transforms/GVN/noalias.ll b/test/Transforms/GVN/noalias.ll new file mode 100644 index 000000000000..6c310fad7ec6 --- /dev/null +++ b/test/Transforms/GVN/noalias.ll @@ -0,0 +1,43 @@ +; RUN: opt -scoped-noalias -basicaa -gvn -S < %s | FileCheck %s + +define i32 @test1(i32* %p, i32* %q) { +; CHECK-LABEL: @test1(i32* %p, i32* %q) +; CHECK: load i32* %p +; CHECK-NOT: noalias +; CHECK: %c = add i32 %a, %a + %a = load i32* %p, !noalias !0 + %b = load i32* %p + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test2(i32* %p, i32* %q) { +; CHECK-LABEL: @test2(i32* %p, i32* %q) +; CHECK: load i32* %p, !alias.scope !0 +; CHECK: %c = add i32 %a, %a + %a = load i32* %p, !alias.scope !0 + %b = load i32* %p, !alias.scope !0 + %c = add i32 %a, %b + ret i32 %c +} + +; FIXME: In this case we can do better than intersecting the scopes, and can +; concatenate them instead. Both loads are in the same basic block, the first +; makes the second safe to speculatively execute, and there are no calls that may +; throw in between. +define i32 @test3(i32* %p, i32* %q) { +; CHECK-LABEL: @test3(i32* %p, i32* %q) +; CHECK: load i32* %p, !alias.scope !1 +; CHECK: %c = add i32 %a, %a + %a = load i32* %p, !alias.scope !1 + %b = load i32* %p, !alias.scope !2 + %c = add i32 %a, %b + ret i32 %c +} + +declare i32 @foo(i32*) readonly + +!0 = !{!0} +!1 = !{!1} +!2 = !{!0, !1} + diff --git a/test/Transforms/GVN/pre-gep-load.ll b/test/Transforms/GVN/pre-gep-load.ll new file mode 100644 index 000000000000..3ee3a37b81ad --- /dev/null +++ b/test/Transforms/GVN/pre-gep-load.ll @@ -0,0 +1,49 @@ +; RUN: opt < %s -basicaa -gvn -enable-load-pre -S | FileCheck %s +target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-gnu" + +define double @foo(i32 %stat, i32 %i, double** %p) { +; CHECK-LABEL: @foo( +entry: + switch i32 %stat, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb + i32 2, label %sw.bb2 + ] + +sw.bb: ; preds = %entry, %entry + %idxprom = sext i32 %i to i64 + %arrayidx = getelementptr inbounds double** %p, i64 0 + %0 = load double** %arrayidx, align 8 + %arrayidx1 = getelementptr inbounds double* %0, i64 %idxprom + %1 = load double* %arrayidx1, align 8 + %sub = fsub double %1, 1.000000e+00 + %cmp = fcmp olt double %sub, 0.000000e+00 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %sw.bb + br label %return + +if.end: ; preds = %sw.bb + br label %sw.bb2 + +sw.bb2: ; preds = %if.end, %entry + %idxprom3 = sext i32 %i to i64 + %arrayidx4 = getelementptr inbounds double** %p, i64 0 + %2 = load double** %arrayidx4, align 8 + %arrayidx5 = getelementptr inbounds double* %2, i64 %idxprom3 + %3 = load double* %arrayidx5, align 8 +; CHECK: sw.bb2: +; CHECK-NEXT-NOT: sext +; CHECK-NEXT: phi double [ +; CHECK-NOT: load + %sub6 = fsub double 3.000000e+00, %3 + br label %return + +sw.default: ; preds = %entry + br label %return + +return: ; preds = %sw.default, %sw.bb2, %if.then + %retval.0 = phi double [ 0.000000e+00, %sw.default ], [ %sub6, %sw.bb2 ], [ %sub, %if.then ] + ret double %retval.0 +} diff --git a/test/Transforms/GVN/preserve-tbaa.ll b/test/Transforms/GVN/preserve-tbaa.ll index c52ed96c23c1..587d463eef27 100644 --- a/test/Transforms/GVN/preserve-tbaa.ll +++ b/test/Transforms/GVN/preserve-tbaa.ll @@ -25,7 +25,7 @@ for.end: ; preds = %for.body, %entry ret void } -!0 = metadata !{metadata !3, metadata !3, i64 0} -!1 = metadata !{metadata !"omnipotent char", metadata !2} -!2 = metadata !{metadata !"Simple C/C++ TBAA", null} -!3 = metadata !{metadata !"short", metadata !1} +!0 = !{!3, !3, i64 0} +!1 = !{!"omnipotent char", !2} +!2 = !{!"Simple C/C++ TBAA", null} +!3 = !{!"short", !1} diff --git a/test/Transforms/GVN/range.ll b/test/Transforms/GVN/range.ll index 2115fe85661e..37202321a6dc 100644 --- a/test/Transforms/GVN/range.ll +++ b/test/Transforms/GVN/range.ll @@ -82,20 +82,20 @@ define i32 @test8(i32* %p) { ret i32 %c } -; CHECK: ![[DISJOINT_RANGE]] = metadata !{i32 0, i32 2, i32 3, i32 5} -; CHECK: ![[MERGED_RANGE]] = metadata !{i32 0, i32 5} -; CHECK: ![[MERGED_SIGNED_RANGE]] = metadata !{i32 -3, i32 -2, i32 1, i32 2} -; CHECK: ![[MERGED_TEST6]] = metadata !{i32 10, i32 1} -; CHECK: ![[MERGED_TEST7]] = metadata !{i32 3, i32 4, i32 5, i32 2} +; CHECK: ![[DISJOINT_RANGE]] = !{i32 0, i32 2, i32 3, i32 5} +; CHECK: ![[MERGED_RANGE]] = !{i32 0, i32 5} +; CHECK: ![[MERGED_SIGNED_RANGE]] = !{i32 -3, i32 -2, i32 1, i32 2} +; CHECK: ![[MERGED_TEST6]] = !{i32 10, i32 1} +; CHECK: ![[MERGED_TEST7]] = !{i32 3, i32 4, i32 5, i32 2} -!0 = metadata !{i32 0, i32 2} -!1 = metadata !{i32 3, i32 5} -!2 = metadata !{i32 2, i32 5} -!3 = metadata !{i32 -3, i32 -2} -!4 = metadata !{i32 1, i32 2} -!5 = metadata !{i32 10, i32 1} -!6 = metadata !{i32 12, i32 13} -!7 = metadata !{i32 1, i32 2, i32 3, i32 4} -!8 = metadata !{i32 5, i32 1} -!9 = metadata !{i32 1, i32 5} -!10 = metadata !{i32 5, i32 1} +!0 = !{i32 0, i32 2} +!1 = !{i32 3, i32 5} +!2 = !{i32 2, i32 5} +!3 = !{i32 -3, i32 -2} +!4 = !{i32 1, i32 2} +!5 = !{i32 10, i32 1} +!6 = !{i32 12, i32 13} +!7 = !{i32 1, i32 2, i32 3, i32 4} +!8 = !{i32 5, i32 1} +!9 = !{i32 1, i32 5} +!10 = !{i32 5, i32 1} diff --git a/test/Transforms/GVN/tbaa.ll b/test/Transforms/GVN/tbaa.ll index d6412fce59b2..1b3494ca4be3 100644 --- a/test/Transforms/GVN/tbaa.ll +++ b/test/Transforms/GVN/tbaa.ll @@ -74,18 +74,18 @@ define i32 @test7(i8* %p, i8* %q) { declare i32 @foo(i8*) readonly -; CHECK: [[TAGC]] = metadata !{metadata [[TYPEC:!.*]], metadata [[TYPEC]], i64 0} -; CHECK: [[TYPEC]] = metadata !{metadata !"C", metadata [[TYPEA:!.*]]} -; CHECK: [[TYPEA]] = metadata !{metadata !"A", metadata !{{.*}}} -; CHECK: [[TAGB]] = metadata !{metadata [[TYPEB:!.*]], metadata [[TYPEB]], i64 0} -; CHECK: [[TYPEB]] = metadata !{metadata !"B", metadata [[TYPEA]]} -; CHECK: [[TAGA]] = metadata !{metadata [[TYPEA]], metadata [[TYPEA]], i64 0} -!0 = metadata !{metadata !5, metadata !5, i64 0} -!1 = metadata !{metadata !6, metadata !6, i64 0} -!2 = metadata !{metadata !"tbaa root", null} -!3 = metadata !{metadata !7, metadata !7, i64 0} -!4 = metadata !{metadata !8, metadata !8, i64 0} -!5 = metadata !{metadata !"C", metadata !6} -!6 = metadata !{metadata !"A", metadata !2} -!7 = metadata !{metadata !"B", metadata !6} -!8 = metadata !{metadata !"another root", null} +; CHECK: [[TAGC]] = !{[[TYPEC:!.*]], [[TYPEC]], i64 0} +; CHECK: [[TYPEC]] = !{!"C", [[TYPEA:!.*]]} +; CHECK: [[TYPEA]] = !{!"A", !{{.*}}} +; CHECK: [[TAGB]] = !{[[TYPEB:!.*]], [[TYPEB]], i64 0} +; CHECK: [[TYPEB]] = !{!"B", [[TYPEA]]} +; CHECK: [[TAGA]] = !{[[TYPEA]], [[TYPEA]], i64 0} +!0 = !{!5, !5, i64 0} +!1 = !{!6, !6, i64 0} +!2 = !{!"tbaa root", null} +!3 = !{!7, !7, i64 0} +!4 = !{!8, !8, i64 0} +!5 = !{!"C", !6} +!6 = !{!"A", !2} +!7 = !{!"B", !6} +!8 = !{!"another root", null} diff --git a/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll b/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll index 0bdced5114d3..584f0bf467fa 100644 --- a/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll +++ b/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll @@ -5,14 +5,14 @@ @A = global i32 0 ; CHECK: @A = global i32 0 -@D = alias internal i32* @A +@D = internal alias i32* @A ; DEAD-NOT: @D @L1 = alias i32* @A ; CHECK: @L1 = alias i32* @A -@L2 = alias internal i32* @L1 -; CHECK: @L2 = alias internal i32* @L1 +@L2 = internal alias i32* @L1 +; CHECK: @L2 = internal alias i32* @L1 @L3 = alias i32* @L2 ; CHECK: @L3 = alias i32* @L2 diff --git a/test/Transforms/GlobalDCE/2009-02-17-AliasUsesAliasee.ll b/test/Transforms/GlobalDCE/2009-02-17-AliasUsesAliasee.ll index 68933c6ef376..5fb4444c6ba8 100644 --- a/test/Transforms/GlobalDCE/2009-02-17-AliasUsesAliasee.ll +++ b/test/Transforms/GlobalDCE/2009-02-17-AliasUsesAliasee.ll @@ -1,4 +1,4 @@ ; RUN: opt < %s -globaldce -@A = alias internal void ()* @F +@A = internal alias void ()* @F define internal void @F() { ret void } diff --git a/test/Transforms/GlobalDCE/deadblockaddr.ll b/test/Transforms/GlobalDCE/deadblockaddr.ll new file mode 100644 index 000000000000..1ec5994d0043 --- /dev/null +++ b/test/Transforms/GlobalDCE/deadblockaddr.ll @@ -0,0 +1,16 @@ +; RUN: opt -globaldce -simplifycfg -S < %s | FileCheck %s + +; Tests whether globaldce does the right cleanup while removing @bar +; so that a dead BlockAddress reference to foo won't prevent other passes +; to work properly, e.g. simplifycfg +@bar = internal unnamed_addr constant i8* blockaddress(@foo, %L1) + +; CHECK-LABEL: foo +; CHECK-NOT: br label %L1 +; CHECK: ret void +define void @foo() { +entry: + br label %L1 +L1: + ret void +} diff --git a/test/Transforms/GlobalDCE/pr20981.ll b/test/Transforms/GlobalDCE/pr20981.ll new file mode 100644 index 000000000000..0eaa6b899091 --- /dev/null +++ b/test/Transforms/GlobalDCE/pr20981.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -globaldce -S | FileCheck %s + +$c1 = comdat any +; CHECK: $c1 = comdat any + +@a1 = linkonce_odr alias void ()* @f1 +; CHECK: @a1 = linkonce_odr alias void ()* @f1 + +define linkonce_odr void @f1() comdat($c1) { + ret void +} +; CHECK: define linkonce_odr void @f1() comdat($c1) + +define void @g() { + call void @f1() + ret void +} diff --git a/test/Transforms/GlobalOpt/2009-02-15-ResolveAlias.ll b/test/Transforms/GlobalOpt/2009-02-15-ResolveAlias.ll index b98facad3977..8efd01807fdb 100644 --- a/test/Transforms/GlobalOpt/2009-02-15-ResolveAlias.ll +++ b/test/Transforms/GlobalOpt/2009-02-15-ResolveAlias.ll @@ -13,7 +13,7 @@ define void @g() { ret void } -@b = alias internal void ()* @g +@b = internal alias void ()* @g ; CHECK-NOT: @b define void @h() { diff --git a/test/Transforms/GlobalOpt/2009-03-05-dbg.ll b/test/Transforms/GlobalOpt/2009-03-05-dbg.ll index 01089600637b..049eef10eb7a 100644 --- a/test/Transforms/GlobalOpt/2009-03-05-dbg.ll +++ b/test/Transforms/GlobalOpt/2009-03-05-dbg.ll @@ -6,14 +6,14 @@ define i32 @foo(i32 %i) nounwind ssp { entry: %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] - call void @llvm.dbg.value(metadata !{i32 %i}, i64 0, metadata !3) + call void @llvm.dbg.value(metadata i32 %i, i64 0, metadata !3, metadata !{}) %0 = icmp eq i32 %i, 1, !dbg !7 ; <i1> [#uses=1] br i1 %0, label %bb, label %bb1, !dbg !7 bb: ; preds = %entry store i32 0, i32* @Stop, align 4, !dbg !9 %1 = mul nsw i32 %i, 42, !dbg !10 ; <i32> [#uses=1] - call void @llvm.dbg.value(metadata !{i32 %1}, i64 0, metadata !3), !dbg !10 + call void @llvm.dbg.value(metadata i32 %1, i64 0, metadata !3, metadata !{}), !dbg !10 br label %bb2, !dbg !10 bb1: ; preds = %entry @@ -28,7 +28,7 @@ return: ; preds = %bb2 ret i32 %i_addr.0, !dbg !12 } -declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone define i32 @bar() nounwind ssp { entry: @@ -51,29 +51,29 @@ return: ; preds = %bb2 ret i32 %.0, !dbg !19 } -declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone !llvm.dbg.gv = !{!0} -!0 = metadata !{i32 458804, i32 0, metadata !1, metadata !"Stop", metadata !"Stop", metadata !"", metadata !1, i32 2, metadata !2, i1 true, i1 true, i32* @Stop} ; [ DW_TAG_variable ] -!1 = metadata !{i32 458769, metadata !20, i32 1, metadata !"4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", i1 true, metadata !"", i32 0, metadata !21, metadata !21, null, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!2 = metadata !{i32 458788, null, metadata !1, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!3 = metadata !{i32 459009, metadata !4, metadata !"i", metadata !1, i32 4, metadata !2} ; [ DW_TAG_arg_variable ] -!4 = metadata !{i32 458798, i32 0, metadata !1, metadata !"foo", metadata !"foo", metadata !"foo", i32 4, metadata !5, i1 false, i1 true, i32 0, i32 0, null, i32 0, i32 0, null, null, null, null, i32 0} ; [ DW_TAG_subprogram ] -!5 = metadata !{i32 458773, metadata !1, null, metadata !1, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !6, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!6 = metadata !{metadata !2, metadata !2} -!7 = metadata !{i32 5, i32 0, metadata !8, null} -!8 = metadata !{i32 458763, metadata !20, metadata !4, i32 0, i32 0, i32 0} ; [ DW_TAG_lexical_block ] -!9 = metadata !{i32 6, i32 0, metadata !8, null} -!10 = metadata !{i32 7, i32 0, metadata !8, null} -!11 = metadata !{i32 9, i32 0, metadata !8, null} -!12 = metadata !{i32 11, i32 0, metadata !8, null} -!13 = metadata !{i32 14, i32 0, metadata !14, null} -!14 = metadata !{i32 458763, metadata !20, metadata !15, i32 0, i32 0, i32 0} ; [ DW_TAG_lexical_block ] -!15 = metadata !{i32 458798, i32 0, metadata !1, metadata !"bar", metadata !"bar", metadata !"bar", i32 13, metadata !16, i1 false, i1 true, i32 0, i32 0, null, i32 0, i32 0, null, null, null, null, i32 0} ; [ DW_TAG_subprogram ] -!16 = metadata !{i32 458773, metadata !1, null, metadata !1, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !17, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!17 = metadata !{metadata !2} -!18 = metadata !{i32 15, i32 0, metadata !14, null} -!19 = metadata !{i32 16, i32 0, metadata !14, null} -!20 = metadata !{metadata !"g.c", metadata !"/tmp"} -!21 = metadata !{i32 0} +!0 = !{!"0x34\00Stop\00Stop\00\002\001\001", !1, !1, !2, i32* @Stop} ; [ DW_TAG_variable ] +!1 = !{!"0x11\001\004.2.1 (Based on Apple Inc. build 5658) (LLVM build)\001\00\000\00\000", !20, !21, !21, null, null, null} ; [ DW_TAG_compile_unit ] +!2 = !{!"0x24\00int\000\0032\0032\000\000\005", null, !1} ; [ DW_TAG_base_type ] +!3 = !{!"0x101\00i\004\000", !4, !1, !2} ; [ DW_TAG_arg_variable ] +!4 = !{!"0x2e\00foo\00foo\00foo\004\000\001\000\006\000\000\000", i32 0, !1, !5, null, null, null, null, null} ; [ DW_TAG_subprogram ] +!5 = !{!"0x15\00\000\000\000\000\000\000", !1, null, null, !6, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!6 = !{!2, !2} +!7 = !MDLocation(line: 5, scope: !8) +!8 = !{!"0xb\000\000\000", !20, !4} ; [ DW_TAG_lexical_block ] +!9 = !MDLocation(line: 6, scope: !8) +!10 = !MDLocation(line: 7, scope: !8) +!11 = !MDLocation(line: 9, scope: !8) +!12 = !MDLocation(line: 11, scope: !8) +!13 = !MDLocation(line: 14, scope: !14) +!14 = !{!"0xb\000\000\000", !20, !15} ; [ DW_TAG_lexical_block ] +!15 = !{!"0x2e\00bar\00bar\00bar\0013\000\001\000\006\000\000\000", i32 0, !1, !16, null, null, null, null, null} ; [ DW_TAG_subprogram ] +!16 = !{!"0x15\00\000\000\000\000\000\000", !1, null, null, !17, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!17 = !{!2} +!18 = !MDLocation(line: 15, scope: !14) +!19 = !MDLocation(line: 16, scope: !14) +!20 = !{!"g.c", !"/tmp"} +!21 = !{i32 0} diff --git a/test/Transforms/GlobalOpt/alias-resolve.ll b/test/Transforms/GlobalOpt/alias-resolve.ll index 9d70c708aad8..ebc20c66cf61 100644 --- a/test/Transforms/GlobalOpt/alias-resolve.ll +++ b/test/Transforms/GlobalOpt/alias-resolve.ll @@ -9,12 +9,12 @@ @bar1 = alias void ()* @bar2 ; CHECK: @bar1 = alias void ()* @bar2 -@weak1 = alias weak void ()* @bar2 -; CHECK: @weak1 = alias weak void ()* @bar2 +@weak1 = weak alias void ()* @bar2 +; CHECK: @weak1 = weak alias void ()* @bar2 @bar4 = private unnamed_addr constant [2 x i8*] zeroinitializer -@foo4 = unnamed_addr alias linkonce_odr getelementptr inbounds ([2 x i8*]* @bar4, i32 0, i32 1) -; CHECK: @foo4 = unnamed_addr alias linkonce_odr getelementptr inbounds ([2 x i8*]* @bar4, i32 0, i32 1) +@foo4 = linkonce_odr unnamed_addr alias getelementptr inbounds ([2 x i8*]* @bar4, i32 0, i32 1) +; CHECK: @foo4 = linkonce_odr unnamed_addr alias getelementptr inbounds ([2 x i8*]* @bar4, i32 0, i32 1) define void @bar2() { ret void diff --git a/test/Transforms/GlobalOpt/alias-used-address-space.ll b/test/Transforms/GlobalOpt/alias-used-address-space.ll index 633cd344a796..62e74ba2ab48 100644 --- a/test/Transforms/GlobalOpt/alias-used-address-space.ll +++ b/test/Transforms/GlobalOpt/alias-used-address-space.ll @@ -7,7 +7,7 @@ target datalayout = "p:32:32:32-p1:16:16:16" @i = internal addrspace(1) global i8 42 ; CHECK: @ia = internal addrspace(1) global i8 42 -@ia = alias internal i8 addrspace(1)* @i +@ia = internal alias i8 addrspace(1)* @i @llvm.used = appending global [1 x i8*] [i8* addrspacecast (i8 addrspace(1)* @ca to i8*)], section "llvm.metadata" ; CHECK-DAG: @llvm.used = appending global [1 x i8*] [i8* addrspacecast (i8 addrspace(1)* @ca to i8*)], section "llvm.metadata" @@ -18,8 +18,8 @@ target datalayout = "p:32:32:32-p1:16:16:16" @sameAsUsed = global [1 x i8*] [i8* addrspacecast(i8 addrspace(1)* @ca to i8*)] ; CHECK-DAG: @sameAsUsed = global [1 x i8*] [i8* addrspacecast (i8 addrspace(1)* @c to i8*)] -@ca = alias internal i8 addrspace(1)* @c -; CHECK: @ca = alias internal i8 addrspace(1)* @c +@ca = internal alias i8 addrspace(1)* @c +; CHECK: @ca = internal alias i8 addrspace(1)* @c define i8 addrspace(1)* @h() { ret i8 addrspace(1)* @ca diff --git a/test/Transforms/GlobalOpt/alias-used-section.ll b/test/Transforms/GlobalOpt/alias-used-section.ll index 121793724d72..4dab2f5a02f5 100644 --- a/test/Transforms/GlobalOpt/alias-used-section.ll +++ b/test/Transforms/GlobalOpt/alias-used-section.ll @@ -1,7 +1,7 @@ ; RUN: opt -S -globalopt < %s | FileCheck %s @_Z17in_custom_section = internal global i8 42, section "CUSTOM" -@in_custom_section = dllexport alias internal i8* @_Z17in_custom_section +@in_custom_section = internal dllexport alias i8* @_Z17in_custom_section ; CHECK: @in_custom_section = internal dllexport global i8 42, section "CUSTOM" diff --git a/test/Transforms/GlobalOpt/alias-used.ll b/test/Transforms/GlobalOpt/alias-used.ll index 05ac7f9bddb3..21f06b7be5ff 100644 --- a/test/Transforms/GlobalOpt/alias-used.ll +++ b/test/Transforms/GlobalOpt/alias-used.ll @@ -4,7 +4,7 @@ @i = internal global i8 42 ; CHECK: @ia = internal global i8 42 -@ia = alias internal i8* @i +@ia = internal alias i8* @i @llvm.used = appending global [3 x i8*] [i8* bitcast (void ()* @fa to i8*), i8* bitcast (void ()* @f to i8*), i8* @ca], section "llvm.metadata" ; CHECK-DAG: @llvm.used = appending global [3 x i8*] [i8* bitcast (void ()* @fa to i8*), i8* bitcast (void ()* @f to i8*), i8* @ca], section "llvm.metadata" @@ -18,17 +18,17 @@ @other = global i32* bitcast (void ()* @fa to i32*) ; CHECK-DAG: @other = global i32* bitcast (void ()* @f to i32*) -@fa = alias internal void ()* @f -; CHECK: @fa = alias internal void ()* @f +@fa = internal alias void ()* @f +; CHECK: @fa = internal alias void ()* @f -@fa2 = alias internal void ()* @f +@fa2 = internal alias void ()* @f ; CHECK-NOT: @fa2 -@fa3 = alias internal void ()* @f +@fa3 = internal alias void ()* @f ; CHECK: @fa3 -@ca = alias internal i8* @c -; CHECK: @ca = alias internal i8* @c +@ca = internal alias i8* @c +; CHECK: @ca = internal alias i8* @c define void @f() { ret void diff --git a/test/Transforms/GlobalOpt/constantfold-initializers.ll b/test/Transforms/GlobalOpt/constantfold-initializers.ll index 4a25d661edcf..36de19c1cd84 100644 --- a/test/Transforms/GlobalOpt/constantfold-initializers.ll +++ b/test/Transforms/GlobalOpt/constantfold-initializers.ll @@ -81,10 +81,23 @@ entry: ret void } +@test6_v1 = internal global { i32, i32 } { i32 42, i32 0 }, align 8 +@test6_v2 = global i32 0, align 4 +; CHECK: @test6_v2 = global i32 42, align 4 +define internal void @test6() { + %load = load { i32, i32 }* @test6_v1, align 8 + %xv0 = extractvalue { i32, i32 } %load, 0 + %iv = insertvalue { i32, i32 } %load, i32 %xv0, 1 + %xv1 = extractvalue { i32, i32 } %iv, 1 + store i32 %xv1, i32* @test6_v2, align 4 + ret void +} + @llvm.global_ctors = appending constant - [5 x { i32, void ()* }] + [6 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @test1 }, { i32, void ()* } { i32 65535, void ()* @test2 }, { i32, void ()* } { i32 65535, void ()* @test3 }, { i32, void ()* } { i32 65535, void ()* @test4 }, - { i32, void ()* } { i32 65535, void ()* @test5 }] + { i32, void ()* } { i32 65535, void ()* @test5 }, + { i32, void ()* } { i32 65535, void ()* @test6 }] diff --git a/test/Transforms/GlobalOpt/externally-initialized-global-ctr.ll b/test/Transforms/GlobalOpt/externally-initialized-global-ctr.ll index 9295c2025a2a..675211b64b46 100644 --- a/test/Transforms/GlobalOpt/externally-initialized-global-ctr.ll +++ b/test/Transforms/GlobalOpt/externally-initialized-global-ctr.ll @@ -32,4 +32,4 @@ define void @print() { ret void } -!2009 = metadata !{} +!2009 = !{} diff --git a/test/Transforms/GlobalOpt/metadata.ll b/test/Transforms/GlobalOpt/metadata.ll index ecf3f94196be..fb60b66ab58e 100644 --- a/test/Transforms/GlobalOpt/metadata.ll +++ b/test/Transforms/GlobalOpt/metadata.ll @@ -13,14 +13,20 @@ define i32 @main(i32 %argc, i8** %argv) { } define void @foo(i32 %x) { - call void @llvm.foo(metadata !{i8*** @G, i32 %x}) -; CHECK: call void @llvm.foo(metadata !{null, i32 %x}) +; Note: these arguments look like MDNodes, but they're really syntactic sugar +; for 'MetadataAsValue::get(ValueAsMetadata::get(Value*))'. When @G drops to +; null, the ValueAsMetadata instance gets replaced by metadata !{}, or +; MDNode::get({}). + call void @llvm.foo(metadata i8*** @G, metadata i32 %x) +; CHECK: call void @llvm.foo(metadata ![[EMPTY:[0-9]+]], metadata i32 %x) ret void } -declare void @llvm.foo(metadata) nounwind readnone +declare void @llvm.foo(metadata, metadata) nounwind readnone !named = !{!0} +; CHECK: !named = !{![[NULL:[0-9]+]]} -!0 = metadata !{i8*** @G} -; CHECK: !0 = metadata !{null} +!0 = !{i8*** @G} +; CHECK-DAG: ![[NULL]] = !{null} +; CHECK-DAG: ![[EMPTY]] = !{} diff --git a/test/Transforms/GlobalOpt/pr21191.ll b/test/Transforms/GlobalOpt/pr21191.ll new file mode 100644 index 000000000000..34e15cb3404a --- /dev/null +++ b/test/Transforms/GlobalOpt/pr21191.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -globalopt -S | FileCheck %s + +$c = comdat any +; CHECK: $c = comdat any + +define linkonce_odr void @foo() comdat($c) { + ret void +} +; CHECK: define linkonce_odr void @foo() comdat($c) + +define linkonce_odr void @bar() comdat($c) { + ret void +} +; CHECK: define linkonce_odr void @bar() comdat($c) + +define void @zed() { + call void @foo() + ret void +} diff --git a/test/Transforms/GlobalOpt/preserve-comdats.ll b/test/Transforms/GlobalOpt/preserve-comdats.ll new file mode 100644 index 000000000000..0148f0024b9d --- /dev/null +++ b/test/Transforms/GlobalOpt/preserve-comdats.ll @@ -0,0 +1,37 @@ +; RUN: opt -globalopt -S < %s | FileCheck %s + +$comdat_global = comdat any + +@comdat_global = weak_odr global i8 0, comdat($comdat_global) +@simple_global = internal global i8 0 +; CHECK: @comdat_global = weak_odr global i8 0, comdat{{$}} +; CHECK: @simple_global = internal global i8 42 + +@llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [ + { i32, void ()*, i8* } { i32 65535, void ()* @init_comdat_global, i8* @comdat_global }, + { i32, void ()*, i8* } { i32 65535, void ()* @init_simple_global, i8* null } +] +; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] +; CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @init_comdat_global, i8* @comdat_global }] + +define void @init_comdat_global() { + store i8 42, i8* @comdat_global + ret void +} +; CHECK: define void @init_comdat_global() + +define internal void @init_simple_global() comdat($comdat_global) { + store i8 42, i8* @simple_global + ret void +} +; CHECK-NOT: @init_simple_global() + +define i8* @use_simple() { + ret i8* @simple_global +} +; CHECK: define i8* @use_simple() + +define i8* @use_comdat() { + ret i8* @comdat_global +} +; CHECK: define i8* @use_comdat() diff --git a/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll b/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll index af9f1b38f1a9..82b2120c0e87 100644 --- a/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll +++ b/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll @@ -1,6 +1,6 @@ ; RUN: opt < %s -indvars -S | FileCheck %s ; Test WidenIV::GetExtendedOperandRecurrence. -; add219 should be extended to i64 because it is nsw, even though its +; %add, %sub and %mul should be extended to i64 because it is nsw, even though its ; sext cannot be hoisted outside the loop. 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" @@ -17,14 +17,27 @@ for.body11: ; preds = %entry for.body153: ; preds = %for.body153, %for.body11 br i1 undef, label %for.body170, label %for.body153 -; CHECK: add nsw i64 %indvars.iv, 1 +; CHECK: add nuw nsw i64 %indvars.iv, 1 +; CHECK: sub nsw i64 %indvars.iv, 2 +; CHECK: sub nsw i64 4, %indvars.iv +; CHECK: mul nsw i64 %indvars.iv, 8 for.body170: ; preds = %for.body170, %for.body153 %i2.19 = phi i32 [ %add249, %for.body170 ], [ 0, %for.body153 ] - %add219 = add nsw i32 %i2.19, 1 - %idxprom220 = sext i32 %add219 to i64 + + %add = add nsw i32 %i2.19, 1 + %add.idxprom = sext i32 %add to i64 + + %sub = sub nsw i32 %i2.19, 2 + %sub.idxprom = sext i32 %sub to i64 + + %sub.neg = sub nsw i32 4, %i2.19 + %sub.neg.idxprom = sext i32 %sub.neg to i64 + + %mul = mul nsw i32 %i2.19, 8 + %mul.idxprom = sext i32 %mul to i64 + %add249 = add nsw i32 %i2.19, %shl132 br label %for.body170 - for.end285: ; preds = %entry ret void } diff --git a/test/Transforms/IndVarSimplify/NVPTX/lit.local.cfg b/test/Transforms/IndVarSimplify/NVPTX/lit.local.cfg new file mode 100644 index 000000000000..2cb98eb371b2 --- /dev/null +++ b/test/Transforms/IndVarSimplify/NVPTX/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'NVPTX' in config.root.targets: + config.unsupported = True diff --git a/test/Transforms/IndVarSimplify/NVPTX/no-widen-expensive.ll b/test/Transforms/IndVarSimplify/NVPTX/no-widen-expensive.ll new file mode 100644 index 000000000000..8744b19d5e28 --- /dev/null +++ b/test/Transforms/IndVarSimplify/NVPTX/no-widen-expensive.ll @@ -0,0 +1,37 @@ +; RUN: opt < %s -indvars -S | FileCheck %s + +target triple = "nvptx64-unknown-unknown" + +; For the nvptx64 architecture, the cost of an arithmetic instruction on a +; 64-bit integer is twice as expensive as that on a 32-bit integer, because the +; hardware needs to simulate a 64-bit integer using two 32-bit integers. +; Therefore, in this particular architecture, we should not widen induction +; variables to 64-bit integers even though i64 is a legal type in the 64-bit +; PTX ISA. + +define void @indvar_32_bit(i32 %n, i32* nocapture %output) { +; CHECK-LABEL: @indvar_32_bit +entry: + %cmp5 = icmp sgt i32 %n, 0 + br i1 %cmp5, label %for.body.preheader, label %for.end + +for.body.preheader: ; preds = %entry + br label %for.body + +for.body: ; preds = %for.body.preheader, %for.body + %i.06 = phi i32 [ 0, %for.body.preheader ], [ %add, %for.body ] +; CHECK: phi i32 + %mul = mul nsw i32 %i.06, %i.06 + %0 = sext i32 %i.06 to i64 + %arrayidx = getelementptr inbounds i32* %output, i64 %0 + store i32 %mul, i32* %arrayidx, align 4 + %add = add nsw i32 %i.06, 3 + %cmp = icmp slt i32 %add, %n + br i1 %cmp, label %for.body, label %for.end.loopexit + +for.end.loopexit: ; preds = %for.body + br label %for.end + +for.end: ; preds = %for.end.loopexit, %entry + ret void +} diff --git a/test/Transforms/IndVarSimplify/backedge-on-min-max.ll b/test/Transforms/IndVarSimplify/backedge-on-min-max.ll new file mode 100644 index 000000000000..250ff9a2eca6 --- /dev/null +++ b/test/Transforms/IndVarSimplify/backedge-on-min-max.ll @@ -0,0 +1,453 @@ +; RUN: opt < %s -indvars -S | FileCheck %s + +;; --- signed --- + +define void @min.signed.1(i32* %a, i32 %a_len, i32 %n) { +; CHECK-LABEL: @min.signed.1 + entry: + %smin.cmp = icmp slt i32 %a_len, %n + %smin = select i1 %smin.cmp, i32 %a_len, i32 %n + %entry.cond = icmp slt i32 0, %smin + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp slt i32 %idx, %a_len + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp slt i32 %idx.inc, %smin + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @min.signed.2(i32* %a, i32 %a_len, i32 %n) { +; CHECK-LABEL: @min.signed.2 + entry: + %smin.cmp = icmp slt i32 %a_len, %n + %smin = select i1 %smin.cmp, i32 %a_len, i32 %n + %entry.cond = icmp slt i32 0, %smin + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp sgt i32 %a_len, %idx + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp slt i32 %idx.inc, %smin + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @min.signed.3(i32* %a, i32 %n) { +; CHECK-LABEL: @min.signed.3 + entry: + %smin.cmp = icmp slt i32 42, %n + %smin = select i1 %smin.cmp, i32 42, i32 %n + %entry.cond = icmp slt i32 0, %smin + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp slt i32 %idx, 42 + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp slt i32 %idx.inc, %smin + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @min.signed.4(i32* %a, i32 %n) { +; CHECK-LABEL: @min.signed.4 + entry: + %smin.cmp = icmp slt i32 42, %n + %smin = select i1 %smin.cmp, i32 42, i32 %n + %entry.cond = icmp slt i32 0, %smin + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp sgt i32 42, %idx + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp slt i32 %idx.inc, %smin + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @max.signed.1(i32* %a, i32 %a_len, i32 %n) { +; CHECK-LABEL: @max.signed.1 + entry: + %smax.cmp = icmp sgt i32 %a_len, %n + %smax = select i1 %smax.cmp, i32 %a_len, i32 %n + %entry.cond = icmp sgt i32 0, %smax + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp sgt i32 %idx, %a_len + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp sgt i32 %idx.inc, %smax + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @max.signed.2(i32* %a, i32 %a_len, i32 %n) { +; CHECK-LABEL: @max.signed.2 + entry: + %smax.cmp = icmp sgt i32 %a_len, %n + %smax = select i1 %smax.cmp, i32 %a_len, i32 %n + %entry.cond = icmp sgt i32 0, %smax + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp slt i32 %a_len, %idx + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp sgt i32 %idx.inc, %smax + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @max.signed.3(i32* %a, i32 %n, i32 %init) { +; CHECK-LABEL: @max.signed.3 + entry: + %smax.cmp = icmp sgt i32 42, %n + %smax = select i1 %smax.cmp, i32 42, i32 %n + %entry.cond = icmp sgt i32 %init, %smax + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp sgt i32 %idx, 42 + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp sgt i32 %idx.inc, %smax + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @max.signed.4(i32* %a, i32 %n, i32 %init) { +; CHECK-LABEL: @max.signed.4 + entry: + %smax.cmp = icmp sgt i32 42, %n + %smax = select i1 %smax.cmp, i32 42, i32 %n + %entry.cond = icmp sgt i32 %init, %smax + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp slt i32 42, %idx + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp sgt i32 %idx.inc, %smax + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +;; --- unsigned --- + +define void @min.unsigned.1(i32* %a, i32 %a_len, i32 %n) { +; CHECK-LABEL: @min.unsigned.1 + entry: + %umin.cmp = icmp ult i32 %a_len, %n + %umin = select i1 %umin.cmp, i32 %a_len, i32 %n + %entry.cond = icmp ult i32 5, %umin + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp ult i32 %idx, %a_len + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp ult i32 %idx.inc, %umin + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @min.unsigned.2(i32* %a, i32 %a_len, i32 %n) { +; CHECK-LABEL: @min.unsigned.2 + entry: + %umin.cmp = icmp ult i32 %a_len, %n + %umin = select i1 %umin.cmp, i32 %a_len, i32 %n + %entry.cond = icmp ult i32 5, %umin + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp ugt i32 %a_len, %idx + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp ult i32 %idx.inc, %umin + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @min.unsigned.3(i32* %a, i32 %n) { +; CHECK-LABEL: @min.unsigned.3 + entry: + %umin.cmp = icmp ult i32 42, %n + %umin = select i1 %umin.cmp, i32 42, i32 %n + %entry.cond = icmp ult i32 5, %umin + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp ult i32 %idx, 42 + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp ult i32 %idx.inc, %umin + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @min.unsigned.4(i32* %a, i32 %n) { +; CHECK-LABEL: @min.unsigned.4 + entry: + %umin.cmp = icmp ult i32 42, %n + %umin = select i1 %umin.cmp, i32 42, i32 %n + %entry.cond = icmp ult i32 5, %umin + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp ugt i32 42, %idx + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp ult i32 %idx.inc, %umin + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @max.unsigned.1(i32* %a, i32 %a_len, i32 %n) { +; CHECK-LABEL: @max.unsigned.1 + entry: + %umax.cmp = icmp ugt i32 %a_len, %n + %umax = select i1 %umax.cmp, i32 %a_len, i32 %n + %entry.cond = icmp ugt i32 5, %umax + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp ugt i32 %idx, %a_len + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp ugt i32 %idx.inc, %umax + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @max.unsigned.2(i32* %a, i32 %a_len, i32 %n) { +; CHECK-LABEL: @max.unsigned.2 + entry: + %umax.cmp = icmp ugt i32 %a_len, %n + %umax = select i1 %umax.cmp, i32 %a_len, i32 %n + %entry.cond = icmp ugt i32 5, %umax + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp ult i32 %a_len, %idx + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp ugt i32 %idx.inc, %umax + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @max.unsigned.3(i32* %a, i32 %n, i32 %init) { +; CHECK-LABEL: @max.unsigned.3 + entry: + %umax.cmp = icmp ugt i32 42, %n + %umax = select i1 %umax.cmp, i32 42, i32 %n + %entry.cond = icmp ugt i32 %init, %umax + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp ugt i32 %idx, 42 + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp ugt i32 %idx.inc, %umax + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} + +define void @max.unsigned.4(i32* %a, i32 %n, i32 %init) { +; CHECK-LABEL: @max.unsigned.4 + entry: + %umax.cmp = icmp ugt i32 42, %n + %umax = select i1 %umax.cmp, i32 42, i32 %n + %entry.cond = icmp ugt i32 %init, %umax + br i1 %entry.cond, label %loop, label %exit + + loop: + %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ] + %idx.inc = add i32 %idx, 1 + %in.bounds = icmp ult i32 42, %idx + br i1 %in.bounds, label %ok, label %latch +; CHECK: br i1 true, label %ok, label %latch + + ok: + %addr = getelementptr i32* %a, i32 %idx + store i32 %idx, i32* %addr + br label %latch + + latch: + %be.cond = icmp ugt i32 %idx.inc, %umax + br i1 %be.cond, label %loop, label %exit + + exit: + ret void +} diff --git a/test/Transforms/IndVarSimplify/lftr-extend-const.ll b/test/Transforms/IndVarSimplify/lftr-extend-const.ll index eeffd0f55024..f12c68cacb66 100644 --- a/test/Transforms/IndVarSimplify/lftr-extend-const.ll +++ b/test/Transforms/IndVarSimplify/lftr-extend-const.ll @@ -2,7 +2,7 @@ ; CHECK-LABEL: @foo( ; CHECK-NOT: %lftr.wideiv = trunc i32 %indvars.iv.next to i16 -; CHECK: %exitcond = icmp ne i32 %indvars.iv, 511 +; CHECK: %exitcond = icmp ne i32 %indvars.iv.next, 512 define void @foo() #0 { entry: br label %for.body diff --git a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll index 057669277cca..a7023f24314a 100644 --- a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll +++ b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll @@ -229,10 +229,11 @@ entry: ; loop and the OR instruction is replaced by an ADD keeping the result ; equivalent. ; +; CHECK: sext ; CHECK: loop: ; CHECK: phi i64 ; CHECK-NOT: sext -; CHECK: icmp slt i32 +; CHECK: icmp slt i64 ; CHECK: exit: ; CHECK: add i64 loop: diff --git a/test/Transforms/IndVarSimplify/sharpen-range.ll b/test/Transforms/IndVarSimplify/sharpen-range.ll new file mode 100644 index 000000000000..5392dbc5fc04 --- /dev/null +++ b/test/Transforms/IndVarSimplify/sharpen-range.ll @@ -0,0 +1,113 @@ +;; RUN: opt -S < %s -indvars | FileCheck %s + +;; Check if llvm can narrow !range metadata based on loop entry +;; predicates. + +declare void @abort() + +define i1 @bounded_below_slt(i32* nocapture readonly %buffer) { +; CHECK-LABEL: bounded_below_slt +entry: + %length = load i32* %buffer, !range !0 + %entry.pred = icmp eq i32 %length, 0 + br i1 %entry.pred, label %abort, label %loop.preheader + +loop.preheader: + br label %loop + +loop: +; CHECK: loop + %idx = phi i32 [ %idx.inc, %loop.next ], [ 0, %loop.preheader ] + %oob.pred = icmp slt i32 %idx, %length + br i1 %oob.pred, label %loop.next, label %oob +; CHECK: br i1 true, label %loop.next, label %oob + +loop.next: +; CHECK: loop.next + %idx.inc = add i32 %idx, 1 + %exit.pred = icmp slt i32 %idx.inc, %length + br i1 %exit.pred, label %loop, label %abort.loopexit + +abort.loopexit: + br label %abort + +abort: + ret i1 false + +oob: + tail call void @abort() + ret i1 false +} + +define i1 @bounded_below_sle(i32* nocapture readonly %buffer) { +; CHECK-LABEL: bounded_below_sle +entry: + %length = load i32* %buffer, !range !0 + %entry.pred = icmp eq i32 %length, 0 + br i1 %entry.pred, label %abort, label %loop.preheader + +loop.preheader: + br label %loop + +loop: +; CHECK: loop + %idx = phi i32 [ %idx.inc, %loop.next ], [ 0, %loop.preheader ] + %oob.pred = icmp sle i32 %idx, %length + br i1 %oob.pred, label %loop.next, label %oob +; CHECK: br i1 true, label %loop.next, label %oob + +loop.next: +; CHECK: loop.next + %idx.inc = add i32 %idx, 1 + %exit.pred = icmp sle i32 %idx.inc, %length + br i1 %exit.pred, label %loop, label %abort.loopexit + +abort.loopexit: + br label %abort + +abort: + ret i1 false + +oob: + tail call void @abort() + ret i1 false +} + +;; Assert that we're not making an incorrect transform. + +declare i32 @check(i8*) + +define void @NoChange() { +; CHECK-LABEL: NoChange +entry: + br label %loop.begin + +loop.begin: +; CHECK: loop.begin: + %i.01 = phi i64 [ 2, %entry ], [ %add, %loop.end ] + %cmp = icmp ugt i64 %i.01, 1 +; CHECK: %cmp = icmp ugt i64 %i.01, 1 + br i1 %cmp, label %loop, label %loop.end + +loop: +; CHECK: loop + %.sum = add i64 %i.01, -2 + %v = getelementptr inbounds i8* null, i64 %.sum + %r = tail call i32 @check(i8* %v) + %c = icmp eq i32 %r, 0 + br i1 %c, label %loop.end, label %abort.now + +abort.now: + tail call void @abort() + unreachable + +loop.end: + %add = add i64 %i.01, -1 + %eq = icmp eq i64 %add, 0 + br i1 %eq, label %exit, label %loop.begin + +exit: + ret void +} + +!0 = !{i32 0, i32 100} diff --git a/test/Transforms/IndVarSimplify/strengthen-overflow.ll b/test/Transforms/IndVarSimplify/strengthen-overflow.ll new file mode 100644 index 000000000000..07e489e03382 --- /dev/null +++ b/test/Transforms/IndVarSimplify/strengthen-overflow.ll @@ -0,0 +1,214 @@ +; RUN: opt < %s -indvars -S | FileCheck %s + +define i32 @test.signed.add.0(i32* %array, i32 %length, i32 %init) { +; CHECK-LABEL: @test.signed.add.0 + entry: + %upper = icmp slt i32 %init, %length + br i1 %upper, label %loop, label %exit + + loop: +; CHECK-LABEL: loop + %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ] + %civ.inc = add i32 %civ, 1 +; CHECK: %civ.inc = add nsw i32 %civ, 1 + %cmp = icmp slt i32 %civ.inc, %length + br i1 %cmp, label %latch, label %break + + latch: + store i32 0, i32* %array + %check = icmp slt i32 %civ.inc, %length + br i1 %check, label %loop, label %break + + break: + ret i32 %civ.inc + + exit: + ret i32 42 +} + +define i32 @test.signed.add.1(i32* %array, i32 %length, i32 %init) { +; CHECK-LABEL: @test.signed.add.1 + entry: + %upper = icmp sle i32 %init, %length + br i1 %upper, label %loop, label %exit + + loop: +; CHECK-LABEL: loop + %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ] + %civ.inc = add i32 %civ, 1 +; CHECK: %civ.inc = add i32 %civ, 1 + %cmp = icmp slt i32 %civ.inc, %length + br i1 %cmp, label %latch, label %break + + latch: + store i32 0, i32* %array + %check = icmp slt i32 %civ.inc, %length + br i1 %check, label %loop, label %break + + break: + ret i32 %civ.inc + + exit: + ret i32 42 +} + +define i32 @test.signed.sub.0(i32* %array, i32 %length, i32 %init) { +; CHECK-LABEL: @test.signed.sub.0 + entry: + %upper = icmp sgt i32 %init, %length + br i1 %upper, label %loop, label %exit + + loop: +; CHECK-LABEL: loop + %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ] + %civ.inc = sub i32 %civ, 1 +; CHECK: %civ.inc = sub nsw i32 %civ, 1 + %cmp = icmp slt i32 %civ.inc, %length + br i1 %cmp, label %latch, label %break + + latch: + store i32 0, i32* %array + %check = icmp sgt i32 %civ.inc, %length + br i1 %check, label %loop, label %break + + break: + ret i32 %civ.inc + + exit: + ret i32 42 +} + +define i32 @test.signed.sub.1(i32* %array, i32 %length, i32 %init) { +; CHECK-LABEL: @test.signed.sub.1 + entry: + %upper = icmp sgt i32 %init, %length + br i1 %upper, label %loop, label %exit + + loop: +; CHECK-LABEL: loop + %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ] + %civ.inc = sub i32 %civ, 1 +; CHECK: %civ.inc = sub i32 %civ, 1 + %cmp = icmp slt i32 %civ.inc, %length + br i1 %cmp, label %latch, label %break + + latch: + store i32 0, i32* %array + %check = icmp sge i32 %civ.inc, %length + br i1 %check, label %loop, label %break + + break: + ret i32 %civ.inc + + exit: + ret i32 42 +} + +define i32 @test.unsigned.add.0(i32* %array, i32 %length, i32 %init) { +; CHECK-LABEL: @test.unsigned.add.0 + entry: + %upper = icmp ult i32 %init, %length + br i1 %upper, label %loop, label %exit + + loop: +; CHECK-LABEL: loop + %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ] + %civ.inc = add i32 %civ, 1 +; CHECK: %civ.inc = add nuw i32 %civ, 1 + %cmp = icmp slt i32 %civ.inc, %length + br i1 %cmp, label %latch, label %break + + latch: + store i32 0, i32* %array + %check = icmp ult i32 %civ.inc, %length + br i1 %check, label %loop, label %break + + break: + ret i32 %civ.inc + + exit: + ret i32 42 +} + +define i32 @test.unsigned.add.1(i32* %array, i32 %length, i32 %init) { +; CHECK-LABEL: @test.unsigned.add.1 + entry: + %upper = icmp ule i32 %init, %length + br i1 %upper, label %loop, label %exit + + loop: +; CHECK-LABEL: loop + %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ] + %civ.inc = add i32 %civ, 1 +; CHECK: %civ.inc = add i32 %civ, 1 + %cmp = icmp slt i32 %civ.inc, %length + br i1 %cmp, label %latch, label %break + + latch: + store i32 0, i32* %array + %check = icmp ult i32 %civ.inc, %length + br i1 %check, label %loop, label %break + + break: + ret i32 %civ.inc + + exit: + ret i32 42 +} + +define i32 @test.unsigned.sub.0(i32* %array, i32* %length_ptr, i32 %init) { +; CHECK-LABEL: @test.unsigned.sub.0 + entry: + %length = load i32* %length_ptr, !range !0 + %upper = icmp ult i32 %init, %length + br i1 %upper, label %loop, label %exit + + loop: +; CHECK-LABEL: loop + %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ] + %civ.inc = sub i32 %civ, 2 +; CHECK: %civ.inc = sub nuw i32 %civ, 2 + %cmp = icmp slt i32 %civ.inc, %length + br i1 %cmp, label %latch, label %break + + latch: + store i32 0, i32* %array + %check = icmp ult i32 %civ.inc, %length + br i1 %check, label %loop, label %break + + break: + ret i32 %civ.inc + + exit: + ret i32 42 +} + +define i32 @test.unsigned.sub.1(i32* %array, i32* %length_ptr, i32 %init) { +; CHECK-LABEL: @test.unsigned.sub.1 + entry: + %length = load i32* %length_ptr, !range !1 + %upper = icmp ult i32 %init, %length + br i1 %upper, label %loop, label %exit + + loop: +; CHECK-LABEL: loop + %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ] + %civ.inc = sub i32 %civ, 2 +; CHECK: %civ.inc = sub i32 %civ, 2 + %cmp = icmp slt i32 %civ.inc, %length + br i1 %cmp, label %latch, label %break + + latch: + store i32 0, i32* %array + %check = icmp ult i32 %civ.inc, %length + br i1 %check, label %loop, label %break + + break: + ret i32 %civ.inc + + exit: + ret i32 42 +} + +!0 = !{i32 0, i32 2} +!1 = !{i32 0, i32 42} diff --git a/test/Transforms/IndVarSimplify/use-range-metadata.ll b/test/Transforms/IndVarSimplify/use-range-metadata.ll new file mode 100644 index 000000000000..ea3b12dac391 --- /dev/null +++ b/test/Transforms/IndVarSimplify/use-range-metadata.ll @@ -0,0 +1,37 @@ +;; RUN: opt -S < %s -indvars | FileCheck %s + +;; Check if IndVarSimplify understands !range metadata. + +declare void @abort() + +define i1 @iterate(i32* nocapture readonly %buffer) { +entry: + %length = load i32* %buffer, !range !0 + br label %loop.preheader + +loop.preheader: + br label %loop + +loop: + %idx = phi i32 [ %idx.inc, %loop.next ], [ 0, %loop.preheader ] + %oob.pred = icmp slt i32 %idx, %length + br i1 %oob.pred, label %loop.next, label %oob +; CHECK: br i1 true, label %loop.next, label %oob + +loop.next: + %idx.inc = add i32 %idx, 1 + %exit.pred = icmp slt i32 %idx.inc, %length + br i1 %exit.pred, label %loop, label %abort.loopexit + +abort.loopexit: + br label %abort + +abort: + ret i1 false + +oob: + tail call void @abort() + ret i1 false +} + +!0 = !{i32 1, i32 100} diff --git a/test/Transforms/IndVarSimplify/verify-scev.ll b/test/Transforms/IndVarSimplify/verify-scev.ll index 019f5830d520..b9ce3d63ec99 100644 --- a/test/Transforms/IndVarSimplify/verify-scev.ll +++ b/test/Transforms/IndVarSimplify/verify-scev.ll @@ -380,11 +380,11 @@ for.body48: ; preds = %for.inc221, %for.bo for.body65.lr.ph: ; preds = %for.body48 %0 = load i32* undef, align 4 + %1 = sext i32 %0 to i64 br label %for.body65.us for.body65.us: ; preds = %for.inc219.us, %for.body65.lr.ph - %k.09.us = phi i32 [ %inc.us, %for.inc219.us ], [ 1, %for.body65.lr.ph ] - %idxprom66.us = sext i32 %k.09.us to i64 + %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc219.us ], [ 1, %for.body65.lr.ph ] br i1 undef, label %for.inc219.us, label %if.end72.us if.end72.us: ; preds = %for.body65.us @@ -406,8 +406,8 @@ for.cond152.us: ; preds = %for.cond152.us, %fo br i1 undef, label %for.cond139.loopexit.us, label %for.cond152.us for.inc219.us: ; preds = %for.cond139.loopexit.us, %if.end110.us, %if.end93.us, %for.body65.us - %inc.us = add nsw i32 %k.09.us, 1 - %cmp64.us = icmp sgt i32 %inc.us, %0 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %cmp64.us = icmp sgt i64 %indvars.iv.next, %1 br i1 %cmp64.us, label %for.inc221, label %for.body65.us for.cond139.loopexit.us: ; preds = %for.cond152.us diff --git a/test/Transforms/IndVarSimplify/widen-loop-comp.ll b/test/Transforms/IndVarSimplify/widen-loop-comp.ll new file mode 100644 index 000000000000..0930a0c41390 --- /dev/null +++ b/test/Transforms/IndVarSimplify/widen-loop-comp.ll @@ -0,0 +1,191 @@ +; RUN: opt < %s -indvars -S | FileCheck %s +target triple = "aarch64--linux-gnu" + +; Check the loop exit i32 compare instruction and operand are widened to i64 +; instead of truncating IV before its use in the i32 compare instruction. + +@idx = common global i32 0, align 4 +@e = common global i32 0, align 4 +@ptr = common global i32* null, align 8 + +; CHECK-LABEL: @test1 +; CHECK: for.body.lr.ph: +; CHECK: sext i32 +; CHECK: for.cond: +; CHECK: icmp slt i64 +; CHECK: for.body: +; CHECK: phi i64 + +define i32 @test1() { +entry: + store i32 -1, i32* @idx, align 4 + %0 = load i32* @e, align 4 + %cmp4 = icmp slt i32 %0, 0 + br i1 %cmp4, label %for.end.loopexit, label %for.body.lr.ph + +for.body.lr.ph: + %1 = load i32** @ptr, align 8 + %2 = load i32* @e, align 4 + br label %for.body + +for.cond: + %inc = add nsw i32 %i.05, 1 + %cmp = icmp slt i32 %i.05, %2 + br i1 %cmp, label %for.body, label %for.cond.for.end.loopexit_crit_edge + +for.body: + %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.cond ] + %idxprom = sext i32 %i.05 to i64 + %arrayidx = getelementptr inbounds i32* %1, i64 %idxprom + %3 = load i32* %arrayidx, align 4 + %tobool = icmp eq i32 %3, 0 + br i1 %tobool, label %if.then, label %for.cond + +if.then: + %i.05.lcssa = phi i32 [ %i.05, %for.body ] + store i32 %i.05.lcssa, i32* @idx, align 4 + br label %for.end + +for.cond.for.end.loopexit_crit_edge: + br label %for.end.loopexit + +for.end.loopexit: + br label %for.end + +for.end: + %4 = load i32* @idx, align 4 + ret i32 %4 +} + +; CHECK-LABEL: @test2 +; CHECK: for.body4.us +; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 +; CHECK: %cmp2.us = icmp slt i64 +; CHECK-NOT: %2 = trunc i64 %indvars.iv.next to i32 +; CHECK-NOT: %cmp2.us = icmp slt i32 + +define void @test2([8 x i8]* %a, i8* %b, i8 %limit) { +entry: + %conv = zext i8 %limit to i32 + br i1 undef, label %for.cond1.preheader, label %for.cond1.preheader.us + +for.cond1.preheader.us: + %storemerge5.us = phi i32 [ 0, %entry ], [ %inc14.us, %for.inc13.us ] + br i1 true, label %for.body4.lr.ph.us, label %for.inc13.us + +for.inc13.us: + %inc14.us = add nsw i32 %storemerge5.us, 1 + %cmp.us = icmp slt i32 %inc14.us, 4 + br i1 %cmp.us, label %for.cond1.preheader.us, label %for.end + +for.body4.us: + %storemerge14.us = phi i32 [ 0, %for.body4.lr.ph.us ], [ %inc.us, %for.body4.us ] + %idxprom.us = sext i32 %storemerge14.us to i64 + %arrayidx6.us = getelementptr inbounds [8 x i8]* %a, i64 %idxprom5.us, i64 %idxprom.us + %0 = load i8* %arrayidx6.us, align 1 + %idxprom7.us = zext i8 %0 to i64 + %arrayidx8.us = getelementptr inbounds i8* %b, i64 %idxprom7.us + %1 = load i8* %arrayidx8.us, align 1 + store i8 %1, i8* %arrayidx6.us, align 1 + %inc.us = add nsw i32 %storemerge14.us, 1 + %cmp2.us = icmp slt i32 %inc.us, %conv + br i1 %cmp2.us, label %for.body4.us, label %for.inc13.us + +for.body4.lr.ph.us: + %idxprom5.us = sext i32 %storemerge5.us to i64 + br label %for.body4.us + +for.cond1.preheader: + %storemerge5 = phi i32 [ 0, %entry ], [ %inc14, %for.inc13 ] + br i1 false, label %for.inc13, label %for.inc13 + +for.inc13: + %inc14 = add nsw i32 %storemerge5, 1 + %cmp = icmp slt i32 %inc14, 4 + br i1 %cmp, label %for.cond1.preheader, label %for.end + +for.end: + ret void +} + +; CHECK-LABEL: @test3 +; CHECK: sext i32 %b +; CHECK: for.cond: +; CHECK: phi i64 +; CHECK: icmp slt i64 + +define i32 @test3(i32* %a, i32 %b) { +entry: + br label %for.cond + +for.cond: + %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] + %cmp = icmp slt i32 %i.0, %b + br i1 %cmp, label %for.body, label %for.end + +for.body: + %idxprom = sext i32 %i.0 to i64 + %arrayidx = getelementptr inbounds i32* %a, i64 %idxprom + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %sum.0, %0 + %inc = add nsw i32 %i.0, 1 + br label %for.cond + +for.end: + ret i32 %sum.0 +} + +declare i32 @fn1(i8 signext) + +; PR21030 +; CHECK-LABEL: @test4 +; CHECK: for.body: +; CHECK: phi i32 +; CHECK: icmp sgt i8 + +define i32 @test4(i32 %a) { +entry: + br label %for.body + +for.body: + %c.07 = phi i8 [ -3, %entry ], [ %dec, %for.body ] + %conv6 = zext i8 %c.07 to i32 + %or = or i32 %a, %conv6 + %conv3 = trunc i32 %or to i8 + %call = call i32 @fn1(i8 signext %conv3) + %dec = add i8 %c.07, -1 + %cmp = icmp sgt i8 %dec, -14 + br i1 %cmp, label %for.body, label %for.end + +for.end: + ret i32 0 +} + +; CHECK-LABEL: @test5 +; CHECK: zext i32 %b +; CHECK: for.cond: +; CHECK: phi i64 +; CHECK: icmp ule i64 + +define i32 @test5(i32* %a, i32 %b) { +entry: + br label %for.cond + +for.cond: + %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] + %cmp = icmp ule i32 %i.0, %b + br i1 %cmp, label %for.body, label %for.end + +for.body: + %idxprom = zext i32 %i.0 to i64 + %arrayidx = getelementptr inbounds i32* %a, i64 %idxprom + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %sum.0, %0 + %inc = add nsw i32 %i.0, 1 + br label %for.cond + +for.end: + ret i32 %sum.0 +} diff --git a/test/Transforms/Inline/align.ll b/test/Transforms/Inline/align.ll new file mode 100644 index 000000000000..9ac6d54bfba9 --- /dev/null +++ b/test/Transforms/Inline/align.ll @@ -0,0 +1,98 @@ +; RUN: opt -inline -preserve-alignment-assumptions-during-inlining -S < %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" +target triple = "x86_64-unknown-linux-gnu" + +define void @hello(float* align 128 nocapture %a, float* nocapture readonly %c) #0 { +entry: + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 5 + store float %0, float* %arrayidx, align 4 + ret void +} + +define void @foo(float* nocapture %a, float* nocapture readonly %c) #0 { +entry: + tail call void @hello(float* %a, float* %c) + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %0, float* %arrayidx, align 4 + ret void +} + +; CHECK: define void @foo(float* nocapture %a, float* nocapture readonly %c) #0 { +; CHECK: entry: +; CHECK: %ptrint = ptrtoint float* %a to i64 +; CHECK: %maskedptr = and i64 %ptrint, 127 +; CHECK: %maskcond = icmp eq i64 %maskedptr, 0 +; CHECK: call void @llvm.assume(i1 %maskcond) +; CHECK: %0 = load float* %c, align 4 +; CHECK: %arrayidx.i = getelementptr inbounds float* %a, i64 5 +; CHECK: store float %0, float* %arrayidx.i, align 4 +; CHECK: %1 = load float* %c, align 4 +; CHECK: %arrayidx = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %1, float* %arrayidx, align 4 +; CHECK: ret void +; CHECK: } + +define void @fooa(float* nocapture align 128 %a, float* nocapture readonly %c) #0 { +entry: + tail call void @hello(float* %a, float* %c) + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %0, float* %arrayidx, align 4 + ret void +} + +; CHECK: define void @fooa(float* nocapture align 128 %a, float* nocapture readonly %c) #0 { +; CHECK: entry: +; CHECK: %0 = load float* %c, align 4 +; CHECK: %arrayidx.i = getelementptr inbounds float* %a, i64 5 +; CHECK: store float %0, float* %arrayidx.i, align 4 +; CHECK: %1 = load float* %c, align 4 +; CHECK: %arrayidx = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %1, float* %arrayidx, align 4 +; CHECK: ret void +; CHECK: } + +define void @hello2(float* align 128 nocapture %a, float* align 128 nocapture %b, float* nocapture readonly %c) #0 { +entry: + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 5 + store float %0, float* %arrayidx, align 4 + %arrayidx1 = getelementptr inbounds float* %b, i64 8 + store float %0, float* %arrayidx1, align 4 + ret void +} + +define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +entry: + tail call void @hello2(float* %a, float* %b, float* %c) + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %0, float* %arrayidx, align 4 + ret void +} + +; CHECK: define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +; CHECK: entry: +; CHECK: %ptrint = ptrtoint float* %a to i64 +; CHECK: %maskedptr = and i64 %ptrint, 127 +; CHECK: %maskcond = icmp eq i64 %maskedptr, 0 +; CHECK: call void @llvm.assume(i1 %maskcond) +; CHECK: %ptrint1 = ptrtoint float* %b to i64 +; CHECK: %maskedptr2 = and i64 %ptrint1, 127 +; CHECK: %maskcond3 = icmp eq i64 %maskedptr2, 0 +; CHECK: call void @llvm.assume(i1 %maskcond3) +; CHECK: %0 = load float* %c, align 4 +; CHECK: %arrayidx.i = getelementptr inbounds float* %a, i64 5 +; CHECK: store float %0, float* %arrayidx.i, align 4 +; CHECK: %arrayidx1.i = getelementptr inbounds float* %b, i64 8 +; CHECK: store float %0, float* %arrayidx1.i, align 4 +; CHECK: %1 = load float* %c, align 4 +; CHECK: %arrayidx = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %1, float* %arrayidx, align 4 +; CHECK: ret void +; CHECK: } + +attributes #0 = { nounwind uwtable } + diff --git a/test/Transforms/Inline/byval-tail-call.ll b/test/Transforms/Inline/byval-tail-call.ll index 3a8906aa210f..154f3974b58d 100644 --- a/test/Transforms/Inline/byval-tail-call.ll +++ b/test/Transforms/Inline/byval-tail-call.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -tailcallelim -inline -instcombine -dse -S | FileCheck %s +; RUN: opt < %s -basicaa -tailcallelim -inline -instcombine -dse -S | FileCheck %s ; PR7272 ; Calls that capture byval parameters cannot be marked as tail calls. Other @@ -27,10 +27,13 @@ define internal void @qux(i32* byval %x) { tail call void @ext(i32* null) ret void } + define void @frob(i32* %x) { ; CHECK-LABEL: define void @frob( -; CHECK: alloca i32 -; CHECK: {{^ *}}call void @ext( +; CHECK: %[[POS:.*]] = alloca i32 +; CHECK: %[[VAL:.*]] = load i32* %x +; CHECK: store i32 %[[VAL]], i32* %[[POS]] +; CHECK: {{^ *}}call void @ext(i32* %[[POS]] ; CHECK: tail call void @ext(i32* null) ; CHECK: ret void tail call void @qux(i32* byval %x) diff --git a/test/Transforms/Inline/debug-invoke.ll b/test/Transforms/Inline/debug-invoke.ll index 41d60742fd29..4815e689b8a5 100644 --- a/test/Transforms/Inline/debug-invoke.ll +++ b/test/Transforms/Inline/debug-invoke.ll @@ -4,9 +4,9 @@ ; CHECK: invoke void @test() ; CHECK-NEXT: to label {{.*}} unwind label {{.*}}, !dbg [[INL_LOC:!.*]] -; CHECK: [[EMPTY:.*]] = metadata !{} -; CHECK: [[INL_LOC]] = metadata !{i32 1, i32 0, metadata [[EMPTY]], metadata [[INL_AT:.*]]} -; CHECK: [[INL_AT]] = metadata !{i32 2, i32 0, metadata [[EMPTY]], null} +; CHECK: [[EMPTY:.*]] = !{} +; CHECK: [[INL_LOC]] = !MDLocation(line: 1, scope: [[EMPTY]], inlinedAt: [[INL_AT:.*]]) +; CHECK: [[INL_AT]] = !MDLocation(line: 2, scope: [[EMPTY]]) declare void @test() declare i32 @__gxx_personality_v0(...) @@ -31,7 +31,7 @@ lpad: } !llvm.module.flags = !{!1} -!1 = metadata !{i32 2, metadata !"Debug Info Version", i32 1} -!2 = metadata !{} -!3 = metadata !{i32 1, i32 0, metadata !2, null} -!4 = metadata !{i32 2, i32 0, metadata !2, null} +!1 = !{i32 2, !"Debug Info Version", i32 2} +!2 = !{} +!3 = !MDLocation(line: 1, scope: !2) +!4 = !MDLocation(line: 2, scope: !2) diff --git a/test/Transforms/Inline/ephemeral.ll b/test/Transforms/Inline/ephemeral.ll new file mode 100644 index 000000000000..d1135c6f0c3e --- /dev/null +++ b/test/Transforms/Inline/ephemeral.ll @@ -0,0 +1,32 @@ +; RUN: opt -S -Oz %s | FileCheck %s + +@a = global i32 4 + +define i1 @inner() { + %a1 = load volatile i32* @a + %x1 = add i32 %a1, %a1 + %c = icmp eq i32 %x1, 0 + + ; Here are enough instructions to prevent inlining, but because they are used + ; only by the @llvm.assume intrinsic, they're free (and, thus, inlining will + ; still happen). + %a2 = mul i32 %a1, %a1 + %a3 = sub i32 %a1, 5 + %a4 = udiv i32 %a3, -13 + %a5 = mul i32 %a4, %a4 + %a6 = add i32 %a5, %x1 + %ca = icmp sgt i32 %a6, -7 + tail call void @llvm.assume(i1 %ca) + + ret i1 %c +} + +; @inner() should be inlined for -Oz. +; CHECK-NOT: call i1 @inner +define i1 @outer() optsize { + %r = call i1 @inner() + ret i1 %r +} + +declare void @llvm.assume(i1) nounwind + diff --git a/test/Transforms/Inline/ignore-debug-info.ll b/test/Transforms/Inline/ignore-debug-info.ll index 543a89be0214..8bd6e7c4287b 100644 --- a/test/Transforms/Inline/ignore-debug-info.ll +++ b/test/Transforms/Inline/ignore-debug-info.ll @@ -7,16 +7,16 @@ 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" target triple = "x86_64-unknown-linux-gnu" -declare void @llvm.dbg.declare(metadata, metadata) #1 -declare void @llvm.dbg.value(metadata, i64, metadata) #1 +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1 define <4 x float> @inner_vectors(<4 x float> %a, <4 x float> %b) { entry: - call void @llvm.dbg.value(metadata !{}, i64 0, metadata !{}) + call void @llvm.dbg.value(metadata !{}, i64 0, metadata !{}, metadata !{}) %mul = fmul <4 x float> %a, <float 3.000000e+00, float 3.000000e+00, float 3.000000e+00, float 3.000000e+00> - call void @llvm.dbg.value(metadata !{}, i64 0, metadata !{}) + call void @llvm.dbg.value(metadata !{}, i64 0, metadata !{}, metadata !{}) %mul1 = fmul <4 x float> %b, <float 5.000000e+00, float 5.000000e+00, float 5.000000e+00, float 5.000000e+00> - call void @llvm.dbg.value(metadata !{}, i64 0, metadata !{}) + call void @llvm.dbg.value(metadata !{}, i64 0, metadata !{}, metadata !{}) %add = fadd <4 x float> %mul, %mul1 ret <4 x float> %add } @@ -27,10 +27,10 @@ define float @outer_vectors(<4 x float> %a, <4 x float> %b) { ; CHECK: ret float entry: - call void @llvm.dbg.value(metadata !{}, i64 0, metadata !{}) - call void @llvm.dbg.value(metadata !{}, i64 0, metadata !{}) + call void @llvm.dbg.value(metadata !{}, i64 0, metadata !{}, metadata !{}) + call void @llvm.dbg.value(metadata !{}, i64 0, metadata !{}, metadata !{}) %call = call <4 x float> @inner_vectors(<4 x float> %a, <4 x float> %b) - call void @llvm.dbg.value(metadata !{}, i64 0, metadata !{}) + call void @llvm.dbg.value(metadata !{}, i64 0, metadata !{}, metadata !{}) %vecext = extractelement <4 x float> %call, i32 0 %vecext1 = extractelement <4 x float> %call, i32 1 %add = fadd float %vecext, %vecext1 @@ -47,9 +47,9 @@ attributes #0 = { nounwind readnone } !llvm.module.flags = !{!3, !4} !llvm.ident = !{!5} -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !{}, metadata !2, metadata !2, metadata !""} -!1 = metadata !{metadata !"", metadata !""} -!2 = metadata !{i32 0} -!3 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!4 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} -!5 = metadata !{metadata !""} +!0 = !{!"0x11\004\00\000\00\000\00\000", !1, !2, !2, !{}, !2, !2} ; [ DW_TAG_compile_unit ] +!1 = !{!"", !""} +!2 = !{i32 0} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 1, !"Debug Info Version", i32 2} +!5 = !{!""} diff --git a/test/Transforms/Inline/inline-musttail-varargs.ll b/test/Transforms/Inline/inline-musttail-varargs.ll new file mode 100644 index 000000000000..7a8957488e1c --- /dev/null +++ b/test/Transforms/Inline/inline-musttail-varargs.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -inline -instcombine -S | FileCheck %s + +; We can't inline this thunk yet, but one day we will be able to. And when we +; do, this test case will be ready. + +declare void @ext_method(i8*, i32) + +define linkonce_odr void @thunk(i8* %this, ...) { + %this_adj = getelementptr i8* %this, i32 4 + musttail call void (i8*, ...)* bitcast (void (i8*, i32)* @ext_method to void (i8*, ...)*)(i8* %this_adj, ...) + ret void +} + +define void @thunk_caller(i8* %p) { + call void (i8*, ...)* @thunk(i8* %p, i32 42) + ret void +} +; CHECK-LABEL: define void @thunk_caller(i8* %p) +; CHECK: call void (i8*, ...)* @thunk(i8* %p, i32 42) + +; FIXME: Inline the thunk. This should be significantly easier than inlining +; general varargs functions. diff --git a/test/Transforms/Inline/inline-vla.ll b/test/Transforms/Inline/inline-vla.ll index dc9deaafe743..7da448b83f3a 100644 --- a/test/Transforms/Inline/inline-vla.ll +++ b/test/Transforms/Inline/inline-vla.ll @@ -35,4 +35,4 @@ attributes #2 = { nounwind } !llvm.ident = !{!0} -!0 = metadata !{metadata !"clang version 3.5.0 (trunk 205695) (llvm/trunk 205706)"} +!0 = !{!"clang version 3.5.0 (trunk 205695) (llvm/trunk 205706)"} diff --git a/test/Transforms/Inline/inline_dbg_declare.ll b/test/Transforms/Inline/inline_dbg_declare.ll new file mode 100644 index 000000000000..563cde314160 --- /dev/null +++ b/test/Transforms/Inline/inline_dbg_declare.ll @@ -0,0 +1,96 @@ +; RUN: opt < %s -S -inline | FileCheck %s
+;
+; The purpose of this test is to check that inline pass preserves debug info
+; for variable using the dbg.declare intrinsic.
+;
+;; This test was generated by running this command:
+;; clang.exe -S -O0 -emit-llvm -g foo.c
+;;
+;; foo.c
+;; ==========================
+;; float foo(float x)
+;; {
+;; return x;
+;; }
+;;
+;; void bar(float *dst)
+;; {
+;; dst[0] = foo(dst[0]);
+;; }
+;; ==========================
+
+target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32"
+target triple = "i686-pc-windows-msvc"
+
+; Function Attrs: nounwind
+define float @foo(float %x) #0 {
+entry:
+ %x.addr = alloca float, align 4
+ store float %x, float* %x.addr, align 4
+ call void @llvm.dbg.declare(metadata float* %x.addr, metadata !16, metadata !17), !dbg !18
+ %0 = load float* %x.addr, align 4, !dbg !19
+ ret float %0, !dbg !19
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; CHECK: define void @bar
+
+; Function Attrs: nounwind
+define void @bar(float* %dst) #0 {
+entry:
+
+; CHECK: [[x_addr_i:%[a-zA-Z0-9.]+]] = alloca float, align 4
+
+ %dst.addr = alloca float*, align 4
+ store float* %dst, float** %dst.addr, align 4
+ call void @llvm.dbg.declare(metadata float** %dst.addr, metadata !20, metadata !17), !dbg !21
+ %0 = load float** %dst.addr, align 4, !dbg !22
+ %arrayidx = getelementptr inbounds float* %0, i32 0, !dbg !22
+ %1 = load float* %arrayidx, align 4, !dbg !22
+ %call = call float @foo(float %1), !dbg !22
+
+; CHECK-NOT: call float @foo
+; CHECK: void @llvm.dbg.declare(metadata float* [[x_addr_i]], metadata [[m23:![0-9]+]], metadata !17), !dbg [[m24:![0-9]+]]
+
+ %2 = load float** %dst.addr, align 4, !dbg !22
+ %arrayidx1 = getelementptr inbounds float* %2, i32 0, !dbg !22
+ store float %call, float* %arrayidx1, align 4, !dbg !22
+ ret void, !dbg !23
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!13, !14}
+!llvm.ident = !{!15}
+
+!0 = !{!"0x11\0012\00clang version 3.6.0 (trunk)\000\00\000\00\001", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [foo.c] [DW_LANG_C99]
+!1 = !{!"foo.c", !""}
+!2 = !{}
+!3 = !{!4, !9}
+!4 = !{!"0x2e\00foo\00foo\00\001\000\001\000\000\00256\000\002", !1, !5, !6, null, float (float)* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [scope 2] [foo]
+!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [foo.c]
+!6 = !{!"0x15\00\000\000\000\000\000\000", null, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = !{!8, !8}
+!8 = !{!"0x24\00float\000\0032\0032\000\000\004", null, null} ; [ DW_TAG_base_type ] [float] [line 0, size 32, align 32, offset 0, enc DW_ATE_float]
+!9 = !{!"0x2e\00bar\00bar\00\006\000\001\000\000\00256\000\007", !1, !5, !10, null, void (float*)* @bar, null, null, !2} ; [ DW_TAG_subprogram ] [line 6] [def] [scope 7] [bar]
+!10 = !{!"0x15\00\000\000\000\000\000\000", null, null, null, !11, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!11 = !{null, !12}
+!12 = !{!"0xf\00\000\0032\0032\000\000", null, null, !8} ; [ DW_TAG_pointer_type ] [line 0, size 32, align 32, offset 0] [from float]
+!13 = !{i32 2, !"Dwarf Version", i32 4}
+!14 = !{i32 2, !"Debug Info Version", i32 2}
+!15 = !{!"clang version 3.6.0 (trunk)"}
+!16 = !{!"0x101\00x\0016777217\000", !4, !5, !8} ; [ DW_TAG_arg_variable ] [x] [line 1]
+!17 = !{!"0x102"} ; [ DW_TAG_expression ]
+!18 = !MDLocation(line: 1, column: 17, scope: !4)
+!19 = !MDLocation(line: 3, column: 5, scope: !4)
+!20 = !{!"0x101\00dst\0016777222\000", !9, !5, !12} ; [ DW_TAG_arg_variable ] [dst] [line 6]
+!21 = !MDLocation(line: 6, column: 17, scope: !9)
+!22 = !MDLocation(line: 8, column: 14, scope: !9)
+!23 = !MDLocation(line: 9, column: 1, scope: !9)
+
+; CHECK: [[m23]] = !{!"0x101\00x\0016777217\000", !4, !5, !8, !22} ; [ DW_TAG_arg_variable ] [x] [line 1]
+; CHECK: [[m24]] = !MDLocation(line: 1, column: 17, scope: !4, inlinedAt: !22)
diff --git a/test/Transforms/Inline/noalias-calls.ll b/test/Transforms/Inline/noalias-calls.ll new file mode 100644 index 000000000000..c09d2a673297 --- /dev/null +++ b/test/Transforms/Inline/noalias-calls.ll @@ -0,0 +1,44 @@ +; RUN: opt -basicaa -inline -enable-noalias-to-md-conversion -S < %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" +target triple = "x86_64-unknown-linux-gnu" + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #0 +declare void @hey() #0 + +define void @hello(i8* noalias nocapture %a, i8* noalias nocapture readonly %c, i8* nocapture %b) #1 { +entry: + %l = alloca i8, i32 512, align 1 + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 16, i32 16, i1 0) + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %b, i8* %c, i64 16, i32 16, i1 0) + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %c, i64 16, i32 16, i1 0) + call void @hey() + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %l, i8* %c, i64 16, i32 16, i1 0) + ret void +} + +define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #1 { +entry: + tail call void @hello(i8* %a, i8* %c, i8* %b) + ret void +} + +; CHECK: define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #1 { +; CHECK: entry: +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 16, i32 16, i1 false) #0, !noalias !0 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %b, i8* %c, i64 16, i32 16, i1 false) #0, !noalias !3 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %c, i64 16, i32 16, i1 false) #0, !alias.scope !5 +; CHECK: call void @hey() #0, !noalias !5 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %c, i64 16, i32 16, i1 false) #0, !noalias !3 +; CHECK: ret void +; CHECK: } + +attributes #0 = { nounwind } +attributes #1 = { nounwind uwtable } + +; CHECK: !0 = !{!1} +; CHECK: !1 = distinct !{!1, !2, !"hello: %c"} +; CHECK: !2 = distinct !{!2, !"hello"} +; CHECK: !3 = !{!4} +; CHECK: !4 = distinct !{!4, !2, !"hello: %a"} +; CHECK: !5 = !{!4, !1} + diff --git a/test/Transforms/Inline/noalias-cs.ll b/test/Transforms/Inline/noalias-cs.ll new file mode 100644 index 000000000000..da5ddd64ed06 --- /dev/null +++ b/test/Transforms/Inline/noalias-cs.ll @@ -0,0 +1,84 @@ +; RUN: opt -inline -enable-noalias-to-md-conversion -S < %s | FileCheck %s +target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: nounwind uwtable +define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +entry: + %0 = load float* %c, align 4, !noalias !3 + %arrayidx.i = getelementptr inbounds float* %a, i64 5 + store float %0, float* %arrayidx.i, align 4, !alias.scope !7, !noalias !8 + %arrayidx1.i = getelementptr inbounds float* %b, i64 8 + store float %0, float* %arrayidx1.i, align 4, !alias.scope !8, !noalias !7 + %1 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %1, float* %arrayidx, align 4 + ret void +} + +define void @foo(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +entry: + call void @foo2(float* %a, float* %b, float* %c), !noalias !0 + call void @foo2(float* %b, float* %b, float* %a), !alias.scope !0 + ret void +} + +; CHECK: define void @foo(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +; CHECK: entry: +; CHECK: %0 = load float* %c, align 4, !noalias !6 +; CHECK: %arrayidx.i.i = getelementptr inbounds float* %a, i64 5 +; CHECK: store float %0, float* %arrayidx.i.i, align 4, !alias.scope !12, !noalias !13 +; CHECK: %arrayidx1.i.i = getelementptr inbounds float* %b, i64 8 +; CHECK: store float %0, float* %arrayidx1.i.i, align 4, !alias.scope !14, !noalias !15 +; CHECK: %1 = load float* %c, align 4, !noalias !16 +; CHECK: %arrayidx.i = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %1, float* %arrayidx.i, align 4, !noalias !16 +; CHECK: %2 = load float* %a, align 4, !alias.scope !16, !noalias !17 +; CHECK: %arrayidx.i.i1 = getelementptr inbounds float* %b, i64 5 +; CHECK: store float %2, float* %arrayidx.i.i1, align 4, !alias.scope !21, !noalias !22 +; CHECK: %arrayidx1.i.i2 = getelementptr inbounds float* %b, i64 8 +; CHECK: store float %2, float* %arrayidx1.i.i2, align 4, !alias.scope !23, !noalias !24 +; CHECK: %3 = load float* %a, align 4, !alias.scope !16 +; CHECK: %arrayidx.i3 = getelementptr inbounds float* %b, i64 7 +; CHECK: store float %3, float* %arrayidx.i3, align 4, !alias.scope !16 +; CHECK: ret void +; CHECK: } + +attributes #0 = { nounwind uwtable } + +!0 = !{!1} +!1 = distinct !{!1, !2, !"hello: %a"} +!2 = distinct !{!2, !"hello"} +!3 = !{!4, !6} +!4 = distinct !{!4, !5, !"hello2: %a"} +!5 = distinct !{!5, !"hello2"} +!6 = distinct !{!6, !5, !"hello2: %b"} +!7 = !{!4} +!8 = !{!6} + +; CHECK: !0 = !{!1, !3} +; CHECK: !1 = distinct !{!1, !2, !"hello2: %a"} +; CHECK: !2 = distinct !{!2, !"hello2"} +; CHECK: !3 = distinct !{!3, !2, !"hello2: %b"} +; CHECK: !4 = !{!1} +; CHECK: !5 = !{!3} +; CHECK: !6 = !{!7, !9, !10} +; CHECK: !7 = distinct !{!7, !8, !"hello2: %a"} +; CHECK: !8 = distinct !{!8, !"hello2"} +; CHECK: !9 = distinct !{!9, !8, !"hello2: %b"} +; CHECK: !10 = distinct !{!10, !11, !"hello: %a"} +; CHECK: !11 = distinct !{!11, !"hello"} +; CHECK: !12 = !{!7} +; CHECK: !13 = !{!9, !10} +; CHECK: !14 = !{!9} +; CHECK: !15 = !{!7, !10} +; CHECK: !16 = !{!10} +; CHECK: !17 = !{!18, !20} +; CHECK: !18 = distinct !{!18, !19, !"hello2: %a"} +; CHECK: !19 = distinct !{!19, !"hello2"} +; CHECK: !20 = distinct !{!20, !19, !"hello2: %b"} +; CHECK: !21 = !{!18, !10} +; CHECK: !22 = !{!20} +; CHECK: !23 = !{!20, !10} +; CHECK: !24 = !{!18} + diff --git a/test/Transforms/Inline/noalias.ll b/test/Transforms/Inline/noalias.ll new file mode 100644 index 000000000000..674da1e2efbb --- /dev/null +++ b/test/Transforms/Inline/noalias.ll @@ -0,0 +1,76 @@ +; RUN: opt -inline -enable-noalias-to-md-conversion -S < %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" +target triple = "x86_64-unknown-linux-gnu" + +define void @hello(float* noalias nocapture %a, float* nocapture readonly %c) #0 { +entry: + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 5 + store float %0, float* %arrayidx, align 4 + ret void +} + +define void @foo(float* nocapture %a, float* nocapture readonly %c) #0 { +entry: + tail call void @hello(float* %a, float* %c) + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %0, float* %arrayidx, align 4 + ret void +} + +; CHECK: define void @foo(float* nocapture %a, float* nocapture readonly %c) #0 { +; CHECK: entry: +; CHECK: %0 = load float* %c, align 4, !noalias !0 +; CHECK: %arrayidx.i = getelementptr inbounds float* %a, i64 5 +; CHECK: store float %0, float* %arrayidx.i, align 4, !alias.scope !0 +; CHECK: %1 = load float* %c, align 4 +; CHECK: %arrayidx = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %1, float* %arrayidx, align 4 +; CHECK: ret void +; CHECK: } + +define void @hello2(float* noalias nocapture %a, float* noalias nocapture %b, float* nocapture readonly %c) #0 { +entry: + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 5 + store float %0, float* %arrayidx, align 4 + %arrayidx1 = getelementptr inbounds float* %b, i64 8 + store float %0, float* %arrayidx1, align 4 + ret void +} + +define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +entry: + tail call void @hello2(float* %a, float* %b, float* %c) + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %0, float* %arrayidx, align 4 + ret void +} + +; CHECK: define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +; CHECK: entry: +; CHECK: %0 = load float* %c, align 4, !noalias !3 +; CHECK: %arrayidx.i = getelementptr inbounds float* %a, i64 5 +; CHECK: store float %0, float* %arrayidx.i, align 4, !alias.scope !7, !noalias !8 +; CHECK: %arrayidx1.i = getelementptr inbounds float* %b, i64 8 +; CHECK: store float %0, float* %arrayidx1.i, align 4, !alias.scope !8, !noalias !7 +; CHECK: %1 = load float* %c, align 4 +; CHECK: %arrayidx = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %1, float* %arrayidx, align 4 +; CHECK: ret void +; CHECK: } + +attributes #0 = { nounwind uwtable } + +; CHECK: !0 = !{!1} +; CHECK: !1 = distinct !{!1, !2, !"hello: %a"} +; CHECK: !2 = distinct !{!2, !"hello"} +; CHECK: !3 = !{!4, !6} +; CHECK: !4 = distinct !{!4, !5, !"hello2: %a"} +; CHECK: !5 = distinct !{!5, !"hello2"} +; CHECK: !6 = distinct !{!6, !5, !"hello2: %b"} +; CHECK: !7 = !{!4} +; CHECK: !8 = !{!6} + diff --git a/test/Transforms/Inline/noalias2.ll b/test/Transforms/Inline/noalias2.ll new file mode 100644 index 000000000000..9c8f8e22d388 --- /dev/null +++ b/test/Transforms/Inline/noalias2.ll @@ -0,0 +1,97 @@ +; RUN: opt -inline -enable-noalias-to-md-conversion -S < %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" +target triple = "x86_64-unknown-linux-gnu" + +define void @hello(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 { +entry: + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 5 + store float %0, float* %arrayidx, align 4 + ret void +} + +define void @foo(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 { +entry: + tail call void @hello(float* %a, float* %c) + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %0, float* %arrayidx, align 4 + ret void +} + +; CHECK: define void @foo(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 { +; CHECK: entry: +; CHECK: %0 = load float* %c, align 4, !alias.scope !0, !noalias !3 +; CHECK: %arrayidx.i = getelementptr inbounds float* %a, i64 5 +; CHECK: store float %0, float* %arrayidx.i, align 4, !alias.scope !3, !noalias !0 +; CHECK: %1 = load float* %c, align 4 +; CHECK: %arrayidx = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %1, float* %arrayidx, align 4 +; CHECK: ret void +; CHECK: } + +define void @hello2(float* noalias nocapture %a, float* noalias nocapture %b, float* nocapture readonly %c) #0 { +entry: + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 6 + store float %0, float* %arrayidx, align 4 + %arrayidx1 = getelementptr inbounds float* %b, i64 8 + store float %0, float* %arrayidx1, align 4 + ret void +} + +; Check that when hello() is inlined into foo(), and then foo() is inlined into +; foo2(), the noalias scopes are properly concatenated. +define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +entry: + tail call void @foo(float* %a, float* %c) + tail call void @hello2(float* %a, float* %b, float* %c) + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %0, float* %arrayidx, align 4 + ret void +} + +; CHECK: define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +; CHECK: entry: +; CHECK: %0 = load float* %c, align 4, !alias.scope !5, !noalias !10 +; CHECK: %arrayidx.i.i = getelementptr inbounds float* %a, i64 5 +; CHECK: store float %0, float* %arrayidx.i.i, align 4, !alias.scope !10, !noalias !5 +; CHECK: %1 = load float* %c, align 4, !alias.scope !13, !noalias !14 +; CHECK: %arrayidx.i = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %1, float* %arrayidx.i, align 4, !alias.scope !14, !noalias !13 +; CHECK: %2 = load float* %c, align 4, !noalias !15 +; CHECK: %arrayidx.i1 = getelementptr inbounds float* %a, i64 6 +; CHECK: store float %2, float* %arrayidx.i1, align 4, !alias.scope !19, !noalias !20 +; CHECK: %arrayidx1.i = getelementptr inbounds float* %b, i64 8 +; CHECK: store float %2, float* %arrayidx1.i, align 4, !alias.scope !20, !noalias !19 +; CHECK: %3 = load float* %c, align 4 +; CHECK: %arrayidx = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %3, float* %arrayidx, align 4 +; CHECK: ret void +; CHECK: } + +; CHECK: !0 = !{!1} +; CHECK: !1 = distinct !{!1, !2, !"hello: %c"} +; CHECK: !2 = distinct !{!2, !"hello"} +; CHECK: !3 = !{!4} +; CHECK: !4 = distinct !{!4, !2, !"hello: %a"} +; CHECK: !5 = !{!6, !8} +; CHECK: !6 = distinct !{!6, !7, !"hello: %c"} +; CHECK: !7 = distinct !{!7, !"hello"} +; CHECK: !8 = distinct !{!8, !9, !"foo: %c"} +; CHECK: !9 = distinct !{!9, !"foo"} +; CHECK: !10 = !{!11, !12} +; CHECK: !11 = distinct !{!11, !7, !"hello: %a"} +; CHECK: !12 = distinct !{!12, !9, !"foo: %a"} +; CHECK: !13 = !{!8} +; CHECK: !14 = !{!12} +; CHECK: !15 = !{!16, !18} +; CHECK: !16 = distinct !{!16, !17, !"hello2: %a"} +; CHECK: !17 = distinct !{!17, !"hello2"} +; CHECK: !18 = distinct !{!18, !17, !"hello2: %b"} +; CHECK: !19 = !{!16} +; CHECK: !20 = !{!18} + +attributes #0 = { nounwind uwtable } + diff --git a/test/Transforms/Inline/optimization-remarks.ll b/test/Transforms/Inline/optimization-remarks.ll index 9108f3ab14d6..fb1b04788885 100644 --- a/test/Transforms/Inline/optimization-remarks.ll +++ b/test/Transforms/Inline/optimization-remarks.ll @@ -57,4 +57,4 @@ attributes #2 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointe !llvm.ident = !{!0} -!0 = metadata !{metadata !"clang version 3.5.0 "} +!0 = !{!"clang version 3.5.0 "} diff --git a/test/Transforms/Inline/pr21206.ll b/test/Transforms/Inline/pr21206.ll new file mode 100644 index 000000000000..e46003050a9f --- /dev/null +++ b/test/Transforms/Inline/pr21206.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -inline -S | FileCheck %s + +$c = comdat any +; CHECK: $c = comdat any + +define linkonce_odr void @foo() comdat($c) { + ret void +} +; CHECK: define linkonce_odr void @foo() comdat($c) + +define linkonce_odr void @bar() comdat($c) { + ret void +} +; CHECK: define linkonce_odr void @bar() comdat($c) + +define void()* @zed() { + ret void()* @foo +} diff --git a/test/Transforms/InstCombine/2007-09-10-AliasConstFold.ll b/test/Transforms/InstCombine/2007-09-10-AliasConstFold.ll index 7f9bd9e40dcb..625989384d70 100644 --- a/test/Transforms/InstCombine/2007-09-10-AliasConstFold.ll +++ b/test/Transforms/InstCombine/2007-09-10-AliasConstFold.ll @@ -1,7 +1,7 @@ ; RUN: opt < %s -instcombine -S | grep icmp ; PR1646 -@__gthrw_pthread_cancel = alias weak i32 (i32)* @pthread_cancel ; <i32 (i32)*> [#uses=1] +@__gthrw_pthread_cancel = weak alias i32 (i32)* @pthread_cancel ; <i32 (i32)*> [#uses=1] @__gthread_active_ptr.5335 = internal constant i8* bitcast (i32 (i32)* @__gthrw_pthread_cancel to i8*) ; <i8**> [#uses=1] define weak i32 @pthread_cancel(i32) { ret i32 0 diff --git a/test/Transforms/InstCombine/2007-09-17-AliasConstFold2.ll b/test/Transforms/InstCombine/2007-09-17-AliasConstFold2.ll index c7cef752dcc9..3793a860e8e9 100644 --- a/test/Transforms/InstCombine/2007-09-17-AliasConstFold2.ll +++ b/test/Transforms/InstCombine/2007-09-17-AliasConstFold2.ll @@ -1,7 +1,7 @@ ; RUN: opt < %s -instcombine -S | grep icmp ; PR1678 -@A = alias weak void ()* @B ; <void ()*> [#uses=1] +@A = weak alias void ()* @B ; <void ()*> [#uses=1] define weak void @B() { ret void diff --git a/test/Transforms/InstCombine/2007-10-10-EliminateMemCpy.ll b/test/Transforms/InstCombine/2007-10-10-EliminateMemCpy.ll index fe935f96e9e1..656fb34061d9 100644 --- a/test/Transforms/InstCombine/2007-10-10-EliminateMemCpy.ll +++ b/test/Transforms/InstCombine/2007-10-10-EliminateMemCpy.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -instcombine -S | not grep call -; RUN: opt < %s -std-compile-opts -S | not grep xyz +; RUN: opt < %s -O3 -S | not grep xyz target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" @.str = internal constant [4 x i8] c"xyz\00" ; <[4 x i8]*> [#uses=1] diff --git a/test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll b/test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll deleted file mode 100644 index 917d3d9436bc..000000000000 --- a/test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll +++ /dev/null @@ -1,14 +0,0 @@ -; RUN: opt < %s -instcombine -S | grep "ret i.* 0" | count 2 -; PR2048 - -define i32 @i(i32 %a) { - %tmp1 = sdiv i32 %a, -1431655765 - %tmp2 = sdiv i32 %tmp1, 3 - ret i32 %tmp2 -} - -define i8 @j(i8 %a) { - %tmp1 = sdiv i8 %a, 64 - %tmp2 = sdiv i8 %tmp1, 3 - ret i8 %tmp2 -} diff --git a/test/Transforms/InstCombine/2008-05-23-CompareFold.ll b/test/Transforms/InstCombine/2008-05-23-CompareFold.ll index acb259be5eb1..b72967767558 100644 --- a/test/Transforms/InstCombine/2008-05-23-CompareFold.ll +++ b/test/Transforms/InstCombine/2008-05-23-CompareFold.ll @@ -1,5 +1,8 @@ -; RUN: opt < %s -instcombine -S | grep "ret i1 false" +; RUN: opt -instcombine -S < %s | FileCheck %s ; PR2359 + +; CHECK-LABEL: @f( +; CHECK: ret i1 false define i1 @f(i8* %x) { entry: %tmp462 = load i8* %x, align 1 ; <i8> [#uses=1] diff --git a/test/Transforms/InstCombine/2008-11-08-FCmp.ll b/test/Transforms/InstCombine/2008-11-08-FCmp.ll index f33a1f59f61b..f1af7ce2fb12 100644 --- a/test/Transforms/InstCombine/2008-11-08-FCmp.ll +++ b/test/Transforms/InstCombine/2008-11-08-FCmp.ll @@ -4,6 +4,7 @@ ; When inst combining an FCMP with the LHS coming from a uitofp instruction, we ; can't lower it to signed ICMP instructions. +; CHECK-LABEL: @test1( define i1 @test1(i32 %val) { %1 = uitofp i32 %val to double %2 = fcmp ole double %1, 0.000000e+00 @@ -11,6 +12,7 @@ define i1 @test1(i32 %val) { ret i1 %2 } +; CHECK-LABEL: @test2( define i1 @test2(i32 %val) { %1 = uitofp i32 %val to double %2 = fcmp olt double %1, 0.000000e+00 @@ -18,6 +20,7 @@ define i1 @test2(i32 %val) { ; CHECK: ret i1 false } +; CHECK-LABEL: @test3( define i1 @test3(i32 %val) { %1 = uitofp i32 %val to double %2 = fcmp oge double %1, 0.000000e+00 @@ -25,6 +28,7 @@ define i1 @test3(i32 %val) { ; CHECK: ret i1 true } +; CHECK-LABEL: @test4( define i1 @test4(i32 %val) { %1 = uitofp i32 %val to double %2 = fcmp ogt double %1, 0.000000e+00 @@ -32,6 +36,7 @@ define i1 @test4(i32 %val) { ret i1 %2 } +; CHECK-LABEL: @test5( define i1 @test5(i32 %val) { %1 = uitofp i32 %val to double %2 = fcmp ogt double %1, -4.400000e+00 @@ -39,6 +44,7 @@ define i1 @test5(i32 %val) { ; CHECK: ret i1 true } +; CHECK-LABEL: @test6( define i1 @test6(i32 %val) { %1 = uitofp i32 %val to double %2 = fcmp olt double %1, -4.400000e+00 @@ -48,6 +54,7 @@ define i1 @test6(i32 %val) { ; Check that optimizing unsigned >= comparisons correctly distinguishes ; positive and negative constants. <rdar://problem/12029145> +; CHECK-LABEL: @test7( define i1 @test7(i32 %val) { %1 = uitofp i32 %val to double %2 = fcmp oge double %1, 3.200000e+00 diff --git a/test/Transforms/InstCombine/2011-06-13-nsw-alloca.ll b/test/Transforms/InstCombine/2011-06-13-nsw-alloca.ll index a75a4656e68a..c8f0351858ca 100644 --- a/test/Transforms/InstCombine/2011-06-13-nsw-alloca.ll +++ b/test/Transforms/InstCombine/2011-06-13-nsw-alloca.ll @@ -15,7 +15,7 @@ define void @fu1(i32 %parm) nounwind ssp { ; <label>:4 ; preds = %0 %5 = load i32* %1, align 4 - %6 = mul nsw i32 %5, 8 + %6 = shl nsw i32 %5, 3 ; With "nsw", the alloca and its bitcast can be fused: %7 = add nsw i32 %6, 2048 ; CHECK: alloca double @@ -50,7 +50,8 @@ define void @fu2(i32 %parm) nounwind ssp { %7 = add i32 %6, 2048 ; CHECK: alloca i8 %8 = alloca i8, i32 %7 -; CHECK-NEXT: bitcast i8* +; CHECK-NEXT: bitcast double** +; CHECK-NEXT: store i8* %9 = bitcast i8* %8 to double* store double* %9, double** %ptr, align 4 br label %10 diff --git a/test/Transforms/InstCombine/AddOverFlow.ll b/test/Transforms/InstCombine/AddOverFlow.ll index 8f3d429c8d60..bebfd6293f9b 100644 --- a/test/Transforms/InstCombine/AddOverFlow.ll +++ b/test/Transforms/InstCombine/AddOverFlow.ll @@ -36,8 +36,8 @@ define i16 @zero_sign_bit2(i16 %a, i16 %b) { declare i16 @bounded(i16 %input); declare i32 @__gxx_personality_v0(...); -!0 = metadata !{i16 0, i16 32768} ; [0, 32767] -!1 = metadata !{i16 0, i16 32769} ; [0, 32768] +!0 = !{i16 0, i16 32768} ; [0, 32767] +!1 = !{i16 0, i16 32769} ; [0, 32768] define i16 @add_bounded_values(i16 %a, i16 %b) { ; CHECK-LABEL: @add_bounded_values( diff --git a/test/Transforms/InstCombine/add2.ll b/test/Transforms/InstCombine/add2.ll index d7eac4b0fd21..fbbba5954b32 100644 --- a/test/Transforms/InstCombine/add2.ll +++ b/test/Transforms/InstCombine/add2.ll @@ -294,7 +294,7 @@ define i16 @add_cttz(i16 %a) { ret i16 %b } declare i16 @llvm.cttz.i16(i16, i1) -!0 = metadata !{i16 0, i16 8} +!0 = !{i16 0, i16 8} ; Similar to @add_cttz, but in this test, the range implied by the ; intrinsic is more strict. Therefore, ValueTracking uses that range. @@ -312,4 +312,44 @@ define i16 @add_cttz_2(i16 %a) { ; CHECK: or i16 %cttz, -16 ret i16 %b } -!1 = metadata !{i16 0, i16 32} +!1 = !{i16 0, i16 32} + +define i32 @add_or_and(i32 %x, i32 %y) { + %or = or i32 %x, %y + %and = and i32 %x, %y + %add = add i32 %or, %and + ret i32 %add +; CHECK-LABEL: @add_or_and( +; CHECK-NEXT: add i32 %x, %y +; CHECK-NEXT: ret i32 +} + +define i32 @add_nsw_or_and(i32 %x, i32 %y) { + %or = or i32 %x, %y + %and = and i32 %x, %y + %add = add nsw i32 %or, %and + ret i32 %add +; CHECK-LABEL: @add_nsw_or_and( +; CHECK-NEXT: add nsw i32 %x, %y +; CHECK-NEXT: ret i32 +} + +define i32 @add_nuw_or_and(i32 %x, i32 %y) { + %or = or i32 %x, %y + %and = and i32 %x, %y + %add = add nuw i32 %or, %and + ret i32 %add +; CHECK-LABEL: @add_nuw_or_and( +; CHECK-NEXT: add nuw i32 %x, %y +; CHECK-NEXT: ret i32 +} + +define i32 @add_nuw_nsw_or_and(i32 %x, i32 %y) { + %or = or i32 %x, %y + %and = and i32 %x, %y + %add = add nsw nuw i32 %or, %and + ret i32 %add +; CHECK-LABEL: @add_nuw_nsw_or_and( +; CHECK-NEXT: add nuw nsw i32 %x, %y +; CHECK-NEXT: ret i32 +} diff --git a/test/Transforms/InstCombine/add4.ll b/test/Transforms/InstCombine/add4.ll deleted file mode 100644 index f9b7e3b5a079..000000000000 --- a/test/Transforms/InstCombine/add4.ll +++ /dev/null @@ -1,102 +0,0 @@ -; RUN: opt < %s -instcombine -S | FileCheck %s - -define float @test1(float %A, float %B, i1 %C) { -EntryBlock: - ;; A*(1 - uitofp i1 C) -> select C, 0, A - %cf = uitofp i1 %C to float - %mc = fsub float 1.000000e+00, %cf - %p1 = fmul fast float %A, %mc - ret float %p1 -; CHECK-LABEL: @test1( -; CHECK: select i1 %C, float -0.000000e+00, float %A -} - -define float @test2(float %A, float %B, i1 %C) { -EntryBlock: - ;; B*(uitofp i1 C) -> select C, B, 0 - %cf = uitofp i1 %C to float - %p2 = fmul fast float %B, %cf - ret float %p2 -; CHECK-LABEL: @test2( -; CHECK: select i1 %C, float %B, float -0.000000e+00 -} - -define float @test3(float %A, float %B, i1 %C) { -EntryBlock: - ;; select C, 0, B + select C, A, 0 -> select C, A, B - %cf = uitofp i1 %C to float - %s1 = select i1 %C, float 0.000000e+00, float %B - %s2 = select i1 %C, float %A, float 0.000000e+00 - %sum = fadd fast float %s1, %s2 - ret float %sum -; CHECK-LABEL: @test3( -; CHECK: select i1 %C, float %A, float %B -} - -define float @test4(float %A, float %B, i1 %C) { -EntryBlock: - ;; B*(uitofp i1 C) + A*(1 - uitofp i1 C) -> select C, A, B - %cf = uitofp i1 %C to float - %mc = fsub fast float 1.000000e+00, %cf - %p1 = fmul fast float %A, %mc - %p2 = fmul fast float %B, %cf - %s1 = fadd fast float %p2, %p1 - ret float %s1 -; CHECK-LABEL: @test4( -; CHECK: select i1 %C, float %B, float %A -} - -define float @test5(float %A, float %B, i1 %C) { -EntryBlock: - ;; A*(1 - uitofp i1 C) + B*(uitofp i1 C) -> select C, A, B - %cf = uitofp i1 %C to float - %mc = fsub fast float 1.000000e+00, %cf - %p1 = fmul fast float %A, %mc - %p2 = fmul fast float %B, %cf - %s1 = fadd fast float %p1, %p2 - ret float %s1 -; CHECK-LABEL: @test5( -; CHECK: select i1 %C, float %B, float %A -} - -; PR15952 -define float @test6(float %A, float %B, i32 %C) { - %cf = uitofp i32 %C to float - %mc = fsub float 1.000000e+00, %cf - %p1 = fmul fast float %A, %mc - ret float %p1 -; CHECK-LABEL: @test6( -; CHECK: uitofp -} - -define float @test7(float %A, float %B, i32 %C) { - %cf = uitofp i32 %C to float - %p2 = fmul fast float %B, %cf - ret float %p2 -; CHECK-LABEL: @test7( -; CHECK: uitofp -} - -define <4 x float> @test8(<4 x float> %A, <4 x float> %B, <4 x i1> %C) { - ;; B*(uitofp i1 C) + A*(1 - uitofp i1 C) -> select C, A, B - %cf = uitofp <4 x i1> %C to <4 x float> - %mc = fsub fast <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, %cf - %p1 = fmul fast <4 x float> %A, %mc - %p2 = fmul fast <4 x float> %B, %cf - %s1 = fadd fast <4 x float> %p2, %p1 - ret <4 x float> %s1 -; CHECK-LABEL: @test8( -; CHECK: select <4 x i1> %C, <4 x float> %B, <4 x float> %A -} - -define <4 x float> @test9(<4 x float> %A, <4 x float> %B, <4 x i1> %C) { - ;; A*(1 - uitofp i1 C) + B*(uitofp i1 C) -> select C, A, B - %cf = uitofp <4 x i1> %C to <4 x float> - %mc = fsub fast <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, %cf - %p1 = fmul fast <4 x float> %A, %mc - %p2 = fmul fast <4 x float> %B, %cf - %s1 = fadd fast <4 x float> %p1, %p2 - ret <4 x float> %s1 -; CHECK-LABEL: @test9 -; CHECK: select <4 x i1> %C, <4 x float> %B, <4 x float> %A -} diff --git a/test/Transforms/InstCombine/addnegneg.ll b/test/Transforms/InstCombine/addnegneg.ll index ad8791d1e7ee..90f6baf5dd54 100644 --- a/test/Transforms/InstCombine/addnegneg.ll +++ b/test/Transforms/InstCombine/addnegneg.ll @@ -9,4 +9,3 @@ entry: %sub6 = add i32 %sub4, %d ; <i32> [#uses=1] ret i32 %sub6 } - diff --git a/test/Transforms/InstCombine/alias-recursion.ll b/test/Transforms/InstCombine/alias-recursion.ll new file mode 100644 index 000000000000..fa63726d2d33 --- /dev/null +++ b/test/Transforms/InstCombine/alias-recursion.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +%class.A = type { i32 (...)** } + +@0 = constant [1 x i8*] zeroinitializer + +@vtbl = alias getelementptr inbounds ([1 x i8*]* @0, i32 0, i32 0) + +define i32 (%class.A*)* @test() { +; CHECK-LABEL: test +entry: + br i1 undef, label %for.body, label %for.end + +for.body: ; preds = %for.body, %entry + br i1 undef, label %for.body, label %for.end + +for.end: ; preds = %for.body, %entry + %A = phi i32 (%class.A*)** [ bitcast (i8** @vtbl to i32 (%class.A*)**), %for.body ], [ null, %entry ] + %B = load i32 (%class.A*)** %A + ret i32 (%class.A*)* %B +} diff --git a/test/Transforms/InstCombine/align-attr.ll b/test/Transforms/InstCombine/align-attr.ll new file mode 100644 index 000000000000..9f366bf8fab1 --- /dev/null +++ b/test/Transforms/InstCombine/align-attr.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: nounwind uwtable +define i32 @foo1(i32* align 32 %a) #0 { +entry: + %0 = load i32* %a, align 4 + ret i32 %0 + +; CHECK-LABEL: @foo1 +; CHECK-DAG: load i32* %a, align 32 +; CHECK: ret i32 +} + diff --git a/test/Transforms/InstCombine/and-compare.ll b/test/Transforms/InstCombine/and-compare.ll index c30a245e4156..037641b90ad7 100644 --- a/test/Transforms/InstCombine/and-compare.ll +++ b/test/Transforms/InstCombine/and-compare.ll @@ -1,11 +1,15 @@ ; RUN: opt < %s -instcombine -S | \ -; RUN: grep and | count 1 +; RUN: FileCheck %s ; Should be optimized to one and. define i1 @test1(i32 %a, i32 %b) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: %1 = xor i32 %a, %b +; CHECK-NEXT: %2 = and i32 %1, 65280 +; CHECK-NEXT: %tmp = icmp ne i32 %2, 0 +; CHECK-NEXT: ret i1 %tmp %tmp1 = and i32 %a, 65280 ; <i32> [#uses=1] %tmp3 = and i32 %b, 65280 ; <i32> [#uses=1] %tmp = icmp ne i32 %tmp1, %tmp3 ; <i1> [#uses=1] ret i1 %tmp } - diff --git a/test/Transforms/InstCombine/and-xor-merge.ll b/test/Transforms/InstCombine/and-xor-merge.ll index e432a9aef7d1..b9a6a536ce7c 100644 --- a/test/Transforms/InstCombine/and-xor-merge.ll +++ b/test/Transforms/InstCombine/and-xor-merge.ll @@ -1,8 +1,11 @@ -; RUN: opt < %s -instcombine -S | grep and | count 1 -; RUN: opt < %s -instcombine -S | grep xor | count 2 +; RUN: opt < %s -instcombine -S | FileCheck %s ; (x&z) ^ (y&z) -> (x^y)&z define i32 @test1(i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: %tmp61 = xor i32 %x, %y +; CHECK-NEXT: %tmp7 = and i32 %tmp61, %z +; CHECK-NEXT: ret i32 %tmp7 %tmp3 = and i32 %z, %x %tmp6 = and i32 %z, %y %tmp7 = xor i32 %tmp3, %tmp6 @@ -11,9 +14,11 @@ define i32 @test1(i32 %x, i32 %y, i32 %z) { ; (x & y) ^ (x|y) -> x^y define i32 @test2(i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: %tmp7 = xor i32 %y, %x +; CHECK-NEXT: ret i32 %tmp7 %tmp3 = and i32 %y, %x %tmp6 = or i32 %y, %x %tmp7 = xor i32 %tmp3, %tmp6 ret i32 %tmp7 } - diff --git a/test/Transforms/InstCombine/and2.ll b/test/Transforms/InstCombine/and2.ll index e88fd5983003..96b535dda99d 100644 --- a/test/Transforms/InstCombine/and2.ll +++ b/test/Transforms/InstCombine/and2.ll @@ -45,7 +45,7 @@ define <4 x i32> @test5(<4 x i32> %A) { ; Check that we combine "if x!=0 && x!=-1" into "if x+1u>1" define i32 @test6(i64 %x) nounwind { -; CHECK: @test6 +; CHECK-LABEL: @test6( ; CHECK-NEXT: add i64 %x, 1 ; CHECK-NEXT: icmp ugt i64 %x.off, 1 %cmp1 = icmp ne i64 %x, -1 @@ -54,3 +54,26 @@ define i32 @test6(i64 %x) nounwind { %land.ext = zext i1 %.cmp1 to i32 ret i32 %land.ext } + +define i1 @test7(i32 %i, i1 %b) { +; CHECK-LABEL: @test7( +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 %i, 0 +; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP]], %b +; CHECK-NEXT: ret i1 [[AND]] + %cmp1 = icmp slt i32 %i, 1 + %cmp2 = icmp sgt i32 %i, -1 + %and1 = and i1 %cmp1, %b + %and2 = and i1 %and1, %cmp2 + ret i1 %and2 +} + +define i1 @test8(i32 %i) { +; CHECK-LABEL: @test8( +; CHECK-NEXT: [[DEC:%.*]] = add i32 %i, -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[DEC]], 13 +; CHECK-NEXT: ret i1 [[CMP]] + %cmp1 = icmp ne i32 %i, 0 + %cmp2 = icmp ult i32 %i, 14 + %cond = and i1 %cmp1, %cmp2 + ret i1 %cond +} diff --git a/test/Transforms/InstCombine/apint-call-cast-target.ll b/test/Transforms/InstCombine/apint-call-cast-target.ll index 4e98f9b2b3ac..f3a66c324147 100644 --- a/test/Transforms/InstCombine/apint-call-cast-target.ll +++ b/test/Transforms/InstCombine/apint-call-cast-target.ll @@ -5,15 +5,18 @@ target triple = "i686-pc-linux-gnu" define i32 @main() { ; CHECK-LABEL: @main( -; CHECK: call i32 bitcast +; CHECK: %[[call:.*]] = call i7* @ctime(i999* null) +; CHECK: %[[cast:.*]] = ptrtoint i7* %[[call]] to i32 +; CHECK: ret i32 %[[cast]] entry: %tmp = call i32 bitcast (i7* (i999*)* @ctime to i32 (i99*)*)( i99* null ) ret i32 %tmp } define i7* @ctime(i999*) { -; CHECK-LABEL: @ctime( -; CHECK: call i7* bitcast +; CHECK-LABEL: define i7* @ctime( +; CHECK: %[[call:.*]] = call i32 @main() +; CHECK: %[[cast:.*]] = inttoptr i32 %[[call]] to i7* entry: %tmp = call i7* bitcast (i32 ()* @main to i7* ()*)( ) ret i7* %tmp diff --git a/test/Transforms/InstCombine/apint-sub.ll b/test/Transforms/InstCombine/apint-sub.ll index df8ec52b5abd..3b69c17e183a 100644 --- a/test/Transforms/InstCombine/apint-sub.ll +++ b/test/Transforms/InstCombine/apint-sub.ll @@ -95,12 +95,6 @@ define i1024 @test14(i1024 %A) { ret i1024 %D } -define i14 @test15(i14 %A, i14 %B) { - %C = sub i14 0, %A ; <i14> [#uses=1] - %D = srem i14 %B, %C ; <i14> [#uses=1] - ret i14 %D -} - define i51 @test16(i51 %A) { %X = sdiv i51 %A, 1123 ; <i51> [#uses=1] %Y = sub i51 0, %X ; <i51> [#uses=1] diff --git a/test/Transforms/InstCombine/assume-loop-align.ll b/test/Transforms/InstCombine/assume-loop-align.ll new file mode 100644 index 000000000000..19190de2cddd --- /dev/null +++ b/test/Transforms/InstCombine/assume-loop-align.ll @@ -0,0 +1,47 @@ +; RUN: opt -domtree -instcombine -loops -S < %s | FileCheck %s +; Note: The -loops above can be anything that requires the domtree, and is +; necessary to work around a pass-manager bug. + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: nounwind uwtable +define void @foo(i32* %a, i32* %b) #0 { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 63 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %ptrint1 = ptrtoint i32* %b to i64 + %maskedptr2 = and i64 %ptrint1, 63 + %maskcond3 = icmp eq i64 %maskedptr2, 0 + tail call void @llvm.assume(i1 %maskcond3) + br label %for.body + +; CHECK-LABEL: @foo +; CHECK: load i32* {{.*}} align 64 +; CHECK: store i32 {{.*}} align 64 +; CHECK: ret + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %arrayidx = getelementptr inbounds i32* %b, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, 1 + %arrayidx5 = getelementptr inbounds i32* %a, i64 %indvars.iv + store i32 %add, i32* %arrayidx5, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 16 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 1648 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + ret void +} + +; Function Attrs: nounwind +declare void @llvm.assume(i1) #1 + +attributes #0 = { nounwind uwtable } +attributes #1 = { nounwind } + diff --git a/test/Transforms/InstCombine/assume-redundant.ll b/test/Transforms/InstCombine/assume-redundant.ll new file mode 100644 index 000000000000..81fe0945949b --- /dev/null +++ b/test/Transforms/InstCombine/assume-redundant.ll @@ -0,0 +1,55 @@ +; RUN: opt -domtree -instcombine -loops -S < %s | FileCheck %s +; Note: The -loops above can be anything that requires the domtree, and is +; necessary to work around a pass-manager bug. + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.s = type { double* } + +; Function Attrs: nounwind uwtable +define void @_Z3fooR1s(%struct.s* nocapture readonly dereferenceable(8) %x) #0 { + +; CHECK-LABEL: @_Z3fooR1s +; CHECK: call void @llvm.assume +; CHECK-NOT: call void @llvm.assume + +entry: + %a = getelementptr inbounds %struct.s* %x, i64 0, i32 0 + %0 = load double** %a, align 8 + %ptrint = ptrtoint double* %0 to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + br label %for.body + +for.body: ; preds = %for.body, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next.1, %for.body ] + tail call void @llvm.assume(i1 %maskcond) + %arrayidx = getelementptr inbounds double* %0, i64 %indvars.iv + %1 = load double* %arrayidx, align 16 + %add = fadd double %1, 1.000000e+00 + tail call void @llvm.assume(i1 %maskcond) + %mul = fmul double %add, 2.000000e+00 + store double %mul, double* %arrayidx, align 16 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + tail call void @llvm.assume(i1 %maskcond) + %arrayidx.1 = getelementptr inbounds double* %0, i64 %indvars.iv.next + %2 = load double* %arrayidx.1, align 8 + %add.1 = fadd double %2, 1.000000e+00 + tail call void @llvm.assume(i1 %maskcond) + %mul.1 = fmul double %add.1, 2.000000e+00 + store double %mul.1, double* %arrayidx.1, align 8 + %indvars.iv.next.1 = add nuw nsw i64 %indvars.iv.next, 1 + %exitcond.1 = icmp eq i64 %indvars.iv.next, 1599 + br i1 %exitcond.1, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} + +; Function Attrs: nounwind +declare void @llvm.assume(i1) #1 + +attributes #0 = { nounwind uwtable } +attributes #1 = { nounwind } + diff --git a/test/Transforms/InstCombine/assume.ll b/test/Transforms/InstCombine/assume.ll new file mode 100644 index 000000000000..7e45c04622ac --- /dev/null +++ b/test/Transforms/InstCombine/assume.ll @@ -0,0 +1,265 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: nounwind uwtable +define i32 @foo1(i32* %a) #0 { +entry: + %0 = load i32* %a, align 4 + +; Check that the alignment has been upgraded and that the assume has not +; been removed: +; CHECK-LABEL: @foo1 +; CHECK-DAG: load i32* %a, align 32 +; CHECK-DAG: call void @llvm.assume +; CHECK: ret i32 + + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + + ret i32 %0 +} + +; Function Attrs: nounwind uwtable +define i32 @foo2(i32* %a) #0 { +entry: +; Same check as in @foo1, but make sure it works if the assume is first too. +; CHECK-LABEL: @foo2 +; CHECK-DAG: load i32* %a, align 32 +; CHECK-DAG: call void @llvm.assume +; CHECK: ret i32 + + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + + %0 = load i32* %a, align 4 + ret i32 %0 +} + +; Function Attrs: nounwind +declare void @llvm.assume(i1) #1 + +define i32 @simple(i32 %a) #1 { +entry: + +; CHECK-LABEL: @simple +; CHECK: call void @llvm.assume +; CHECK: ret i32 4 + + %cmp = icmp eq i32 %a, 4 + tail call void @llvm.assume(i1 %cmp) + ret i32 %a +} + +; Function Attrs: nounwind uwtable +define i32 @can1(i1 %a, i1 %b, i1 %c) { +entry: + %and1 = and i1 %a, %b + %and = and i1 %and1, %c + tail call void @llvm.assume(i1 %and) + +; CHECK-LABEL: @can1 +; CHECK: call void @llvm.assume(i1 %a) +; CHECK: call void @llvm.assume(i1 %b) +; CHECK: call void @llvm.assume(i1 %c) +; CHECK: ret i32 + + ret i32 5 +} + +; Function Attrs: nounwind uwtable +define i32 @can2(i1 %a, i1 %b, i1 %c) { +entry: + %v = or i1 %a, %b + %w = xor i1 %v, 1 + tail call void @llvm.assume(i1 %w) + +; CHECK-LABEL: @can2 +; CHECK: %[[V1:[^ ]+]] = xor i1 %a, true +; CHECK: call void @llvm.assume(i1 %[[V1]]) +; CHECK: %[[V2:[^ ]+]] = xor i1 %b, true +; CHECK: call void @llvm.assume(i1 %[[V2]]) +; CHECK: ret i32 + + ret i32 5 +} + +define i32 @bar1(i32 %a) #0 { +entry: + %and1 = and i32 %a, 3 + +; CHECK-LABEL: @bar1 +; CHECK: call void @llvm.assume +; CHECK: ret i32 1 + + %and = and i32 %a, 7 + %cmp = icmp eq i32 %and, 1 + tail call void @llvm.assume(i1 %cmp) + + ret i32 %and1 +} + +; Function Attrs: nounwind uwtable +define i32 @bar2(i32 %a) #0 { +entry: +; CHECK-LABEL: @bar2 +; CHECK: call void @llvm.assume +; CHECK: ret i32 1 + + %and = and i32 %a, 7 + %cmp = icmp eq i32 %and, 1 + tail call void @llvm.assume(i1 %cmp) + + %and1 = and i32 %a, 3 + ret i32 %and1 +} + +; Function Attrs: nounwind uwtable +define i32 @bar3(i32 %a, i1 %x, i1 %y) #0 { +entry: + %and1 = and i32 %a, 3 + +; Don't be fooled by other assumes around. +; CHECK-LABEL: @bar3 +; CHECK: call void @llvm.assume +; CHECK: ret i32 1 + + tail call void @llvm.assume(i1 %x) + + %and = and i32 %a, 7 + %cmp = icmp eq i32 %and, 1 + tail call void @llvm.assume(i1 %cmp) + + tail call void @llvm.assume(i1 %y) + + ret i32 %and1 +} + +; Function Attrs: nounwind uwtable +define i32 @bar4(i32 %a, i32 %b) { +entry: + %and1 = and i32 %b, 3 + +; CHECK-LABEL: @bar4 +; CHECK: call void @llvm.assume +; CHECK: call void @llvm.assume +; CHECK: ret i32 1 + + %and = and i32 %a, 7 + %cmp = icmp eq i32 %and, 1 + tail call void @llvm.assume(i1 %cmp) + + %cmp2 = icmp eq i32 %a, %b + tail call void @llvm.assume(i1 %cmp2) + + ret i32 %and1 +} + +define i32 @icmp1(i32 %a) #0 { +entry: + %cmp = icmp sgt i32 %a, 5 + tail call void @llvm.assume(i1 %cmp) + %conv = zext i1 %cmp to i32 + ret i32 %conv + +; CHECK-LABEL: @icmp1 +; CHECK: call void @llvm.assume +; CHECK: ret i32 1 + +} + +; Function Attrs: nounwind uwtable +define i32 @icmp2(i32 %a) #0 { +entry: + %cmp = icmp sgt i32 %a, 5 + tail call void @llvm.assume(i1 %cmp) + %0 = zext i1 %cmp to i32 + %lnot.ext = xor i32 %0, 1 + ret i32 %lnot.ext + +; CHECK-LABEL: @icmp2 +; CHECK: call void @llvm.assume +; CHECK: ret i32 0 +} + +declare void @escape(i32* %a) + +; Do we canonicalize a nonnull assumption on a load into +; metadata form? +define i1 @nonnull1(i32** %a) { +entry: + %load = load i32** %a + %cmp = icmp ne i32* %load, null + tail call void @llvm.assume(i1 %cmp) + tail call void @escape(i32* %load) + %rval = icmp eq i32* %load, null + ret i1 %rval + +; CHECK-LABEL: @nonnull1 +; CHECK: !nonnull +; CHECK-NOT: call void @llvm.assume +; CHECK: ret i1 false +} + +; Make sure the above canonicalization applies only +; to pointer types. Doing otherwise would be illegal. +define i1 @nonnull2(i32* %a) { +entry: + %load = load i32* %a + %cmp = icmp ne i32 %load, 0 + tail call void @llvm.assume(i1 %cmp) + %rval = icmp eq i32 %load, 0 + ret i1 %rval + +; CHECK-LABEL: @nonnull2 +; CHECK-NOT: !nonnull +; CHECK: call void @llvm.assume +} + +; Make sure the above canonicalization does not trigger +; if the assume is control dependent on something else +define i1 @nonnull3(i32** %a, i1 %control) { +entry: + %load = load i32** %a + %cmp = icmp ne i32* %load, null + br i1 %control, label %taken, label %not_taken +taken: + tail call void @llvm.assume(i1 %cmp) + %rval = icmp eq i32* %load, null + ret i1 %rval +not_taken: + ret i1 true + +; CHECK-LABEL: @nonnull3 +; CHECK-NOT: !nonnull +; CHECK: call void @llvm.assume +} + +; Make sure the above canonicalization does not trigger +; if the path from the load to the assume is potentially +; interrupted by an exception being thrown +define i1 @nonnull4(i32** %a) { +entry: + %load = load i32** %a + ;; This call may throw! + tail call void @escape(i32* %load) + %cmp = icmp ne i32* %load, null + tail call void @llvm.assume(i1 %cmp) + %rval = icmp eq i32* %load, null + ret i1 %rval + +; CHECK-LABEL: @nonnull4 +; CHECK-NOT: !nonnull +; CHECK: call void @llvm.assume +} + + + + +attributes #0 = { nounwind uwtable } +attributes #1 = { nounwind } + diff --git a/test/Transforms/InstCombine/assume2.ll b/test/Transforms/InstCombine/assume2.ll new file mode 100644 index 000000000000..c41bbaa04eb7 --- /dev/null +++ b/test/Transforms/InstCombine/assume2.ll @@ -0,0 +1,174 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: nounwind +declare void @llvm.assume(i1) #1 + +; Function Attrs: nounwind uwtable +define i32 @test1(i32 %a) #0 { +entry: +; CHECK-LABEL: @test1 +; CHECK: call void @llvm.assume +; CHECK: ret i32 5 + + %and = and i32 %a, 15 + %cmp = icmp eq i32 %and, 5 + tail call void @llvm.assume(i1 %cmp) + + %and1 = and i32 %a, 7 + ret i32 %and1 +} + +; Function Attrs: nounwind uwtable +define i32 @test2(i32 %a) #0 { +entry: +; CHECK-LABEL: @test2 +; CHECK: call void @llvm.assume +; CHECK: ret i32 2 + + %and = and i32 %a, 15 + %nand = xor i32 %and, -1 + %cmp = icmp eq i32 %nand, 4294967285 + tail call void @llvm.assume(i1 %cmp) + + %and1 = and i32 %a, 7 + ret i32 %and1 +} + +; Function Attrs: nounwind uwtable +define i32 @test3(i32 %a) #0 { +entry: +; CHECK-LABEL: @test3 +; CHECK: call void @llvm.assume +; CHECK: ret i32 5 + + %v = or i32 %a, 4294967280 + %cmp = icmp eq i32 %v, 4294967285 + tail call void @llvm.assume(i1 %cmp) + + %and1 = and i32 %a, 7 + ret i32 %and1 +} + +; Function Attrs: nounwind uwtable +define i32 @test4(i32 %a) #0 { +entry: +; CHECK-LABEL: @test4 +; CHECK: call void @llvm.assume +; CHECK: ret i32 2 + + %v = or i32 %a, 4294967280 + %nv = xor i32 %v, -1 + %cmp = icmp eq i32 %nv, 5 + tail call void @llvm.assume(i1 %cmp) + + %and1 = and i32 %a, 7 + ret i32 %and1 +} + +; Function Attrs: nounwind uwtable +define i32 @test5(i32 %a) #0 { +entry: +; CHECK-LABEL: @test5 +; CHECK: call void @llvm.assume +; CHECK: ret i32 4 + + %v = xor i32 %a, 1 + %cmp = icmp eq i32 %v, 5 + tail call void @llvm.assume(i1 %cmp) + + %and1 = and i32 %a, 7 + ret i32 %and1 +} + +; Function Attrs: nounwind uwtable +define i32 @test6(i32 %a) #0 { +entry: +; CHECK-LABEL: @test6 +; CHECK: call void @llvm.assume +; CHECK: ret i32 5 + + %v = shl i32 %a, 2 + %cmp = icmp eq i32 %v, 20 + tail call void @llvm.assume(i1 %cmp) + + %and1 = and i32 %a, 63 + ret i32 %and1 +} + +; Function Attrs: nounwind uwtable +define i32 @test7(i32 %a) #0 { +entry: +; CHECK-LABEL: @test7 +; CHECK: call void @llvm.assume +; CHECK: ret i32 20 + + %v = lshr i32 %a, 2 + %cmp = icmp eq i32 %v, 5 + tail call void @llvm.assume(i1 %cmp) + + %and1 = and i32 %a, 252 + ret i32 %and1 +} + +; Function Attrs: nounwind uwtable +define i32 @test8(i32 %a) #0 { +entry: +; CHECK-LABEL: @test8 +; CHECK: call void @llvm.assume +; CHECK: ret i32 20 + + %v = lshr i32 %a, 2 + %cmp = icmp eq i32 %v, 5 + tail call void @llvm.assume(i1 %cmp) + + %and1 = and i32 %a, 252 + ret i32 %and1 +} + +; Function Attrs: nounwind uwtable +define i32 @test9(i32 %a) #0 { +entry: +; CHECK-LABEL: @test9 +; CHECK: call void @llvm.assume +; CHECK: ret i32 0 + + %cmp = icmp sgt i32 %a, 5 + tail call void @llvm.assume(i1 %cmp) + + %and1 = and i32 %a, 2147483648 + ret i32 %and1 +} + +; Function Attrs: nounwind uwtable +define i32 @test10(i32 %a) #0 { +entry: +; CHECK-LABEL: @test10 +; CHECK: call void @llvm.assume +; CHECK: ret i32 -2147483648 + + %cmp = icmp sle i32 %a, -2 + tail call void @llvm.assume(i1 %cmp) + + %and1 = and i32 %a, 2147483648 + ret i32 %and1 +} + +; Function Attrs: nounwind uwtable +define i32 @test11(i32 %a) #0 { +entry: +; CHECK-LABEL: @test11 +; CHECK: call void @llvm.assume +; CHECK: ret i32 0 + + %cmp = icmp ule i32 %a, 256 + tail call void @llvm.assume(i1 %cmp) + + %and1 = and i32 %a, 3072 + ret i32 %and1 +} + +attributes #0 = { nounwind uwtable } +attributes #1 = { nounwind } + diff --git a/test/Transforms/InstCombine/atomic.ll b/test/Transforms/InstCombine/atomic.ll index ccee87433f32..98cecefcc294 100644 --- a/test/Transforms/InstCombine/atomic.ll +++ b/test/Transforms/InstCombine/atomic.ll @@ -5,14 +5,6 @@ target triple = "x86_64-apple-macosx10.7.0" ; Check transforms involving atomic operations -define i32* @test1(i8** %p) { -; CHECK-LABEL: define i32* @test1( -; CHECK: load atomic i8** %p monotonic, align 8 - %c = bitcast i8** %p to i32** - %r = load atomic i32** %c monotonic, align 8 - ret i32* %r -} - define i32 @test2(i32* %p) { ; CHECK-LABEL: define i32 @test2( ; CHECK: %x = load atomic i32* %p seq_cst, align 4 diff --git a/test/Transforms/InstCombine/bitcast-alias-function.ll b/test/Transforms/InstCombine/bitcast-alias-function.ll index a6b56f94ffbf..cfec09200dbc 100644 --- a/test/Transforms/InstCombine/bitcast-alias-function.ll +++ b/test/Transforms/InstCombine/bitcast-alias-function.ll @@ -90,10 +90,12 @@ entry: define void @bitcast_alias_scalar(float* noalias %source, float* noalias %dest) nounwind { entry: ; CHECK-LABEL: @bitcast_alias_scalar -; CHECK: bitcast float %tmp to i32 +; CHECK: bitcast float* %source to i32* +; CHECK: load i32* ; CHECK-NOT: fptoui ; CHECK-NOT: uitofp -; CHECK: bitcast i32 %call to float +; CHECK: bitcast float* %dest to i32* +; CHECK: store i32 %tmp = load float* %source, align 8 %call = call float @alias_i32_to_f32(float %tmp) nounwind store float %call, float* %dest, align 8 @@ -104,10 +106,12 @@ entry: define void @bitcast_alias_vector(<2 x float>* noalias %source, <2 x float>* noalias %dest) nounwind { entry: ; CHECK-LABEL: @bitcast_alias_vector -; CHECK: bitcast <2 x float> %tmp to <2 x i32> +; CHECK: bitcast <2 x float>* %source to <2 x i32>* +; CHECK: load <2 x i32>* ; CHECK-NOT: fptoui ; CHECK-NOT: uitofp -; CHECK: bitcast <2 x i32> %call to <2 x float> +; CHECK: bitcast <2 x float>* %dest to <2 x i32>* +; CHECK: store <2 x i32> %tmp = load <2 x float>* %source, align 8 %call = call <2 x float> @alias_v2i32_to_v2f32(<2 x float> %tmp) nounwind store <2 x float> %call, <2 x float>* %dest, align 8 @@ -118,9 +122,11 @@ entry: define void @bitcast_alias_vector_scalar_same_size(<2 x float>* noalias %source, <2 x float>* noalias %dest) nounwind { entry: ; CHECK-LABEL: @bitcast_alias_vector_scalar_same_size -; CHECK: bitcast <2 x float> %tmp to i64 +; CHECK: bitcast <2 x float>* %source to i64* +; CHECK: load i64* ; CHECK: %call = call i64 @func_i64 -; CHECK: bitcast i64 %call to <2 x float> +; CHECK: bitcast <2 x float>* %dest to i64* +; CHECK: store i64 %tmp = load <2 x float>* %source, align 8 %call = call <2 x float> @alias_v2f32_to_i64(<2 x float> %tmp) nounwind store <2 x float> %call, <2 x float>* %dest, align 8 @@ -130,9 +136,11 @@ entry: define void @bitcast_alias_scalar_vector_same_size(i64* noalias %source, i64* noalias %dest) nounwind { entry: ; CHECK-LABEL: @bitcast_alias_scalar_vector_same_size -; CHECK: bitcast i64 %tmp to <2 x float> +; CHECK: bitcast i64* %source to <2 x float>* +; CHECK: load <2 x float>* ; CHECK: call <2 x float> @func_v2f32 -; CHECK: bitcast <2 x float> %call to i64 +; CHECK: bitcast i64* %dest to <2 x float>* +; CHECK: store <2 x float> %tmp = load i64* %source, align 8 %call = call i64 @alias_i64_to_v2f32(i64 %tmp) nounwind store i64 %call, i64* %dest, align 8 @@ -142,9 +150,11 @@ entry: define void @bitcast_alias_vector_ptrs_same_size(<2 x i64*>* noalias %source, <2 x i64*>* noalias %dest) nounwind { entry: ; CHECK-LABEL: @bitcast_alias_vector_ptrs_same_size -; CHECK: bitcast <2 x i64*> %tmp to <2 x i32*> +; CHECK: bitcast <2 x i64*>* %source to <2 x i32*>* +; CHECK: load <2 x i32*>* ; CHECK: call <2 x i32*> @func_v2i32p -; CHECK: bitcast <2 x i32*> %call to <2 x i64*> +; CHECK: bitcast <2 x i64*>* %dest to <2 x i32*>* +; CHECK: store <2 x i32*> %tmp = load <2 x i64*>* %source, align 8 %call = call <2 x i64*> @alias_v2i32p_to_v2i64p(<2 x i64*> %tmp) nounwind store <2 x i64*> %call, <2 x i64*>* %dest, align 8 diff --git a/test/Transforms/InstCombine/bitcast-store.ll b/test/Transforms/InstCombine/bitcast-store.ll index e46b5c82d9ff..ea4d680ade5a 100644 --- a/test/Transforms/InstCombine/bitcast-store.ll +++ b/test/Transforms/InstCombine/bitcast-store.ll @@ -10,11 +10,11 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 @G = external constant [5 x i8*] ; CHECK-LABEL: @foo -; CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([5 x i8*]* @G, i64 0, i64 2) to i32 (...)**), i32 (...)*** %0, align 16, !tag !0 -define void @foo(%struct.A* %a) nounwind { +; CHECK: store i32 %x, i32* %{{.*}}, align 16, !noalias !0 +define void @foo(i32 %x, float* %p) nounwind { entry: - %0 = bitcast %struct.A* %a to i8*** - store i8** getelementptr inbounds ([5 x i8*]* @G, i64 0, i64 2), i8*** %0, align 16, !tag !0 + %x.cast = bitcast i32 %x to float + store float %x.cast, float* %p, align 16, !noalias !0 ret void } @@ -32,4 +32,4 @@ entry: ret void } -!0 = metadata !{metadata !"hello"} +!0 = !{!0} diff --git a/test/Transforms/InstCombine/bswap-fold.ll b/test/Transforms/InstCombine/bswap-fold.ll index 442ce58421e1..63b0775e4aff 100644 --- a/test/Transforms/InstCombine/bswap-fold.ll +++ b/test/Transforms/InstCombine/bswap-fold.ll @@ -1,63 +1,79 @@ -; RUN: opt < %s -instcombine -S | not grep call.*bswap +; RUN: opt < %s -instcombine -S | FileCheck %s define i1 @test1(i16 %tmp2) { +; CHECK-LABEL: @test1 +; CHECK-NEXT: %tmp = icmp eq i16 %tmp2, 256 +; CHECK-NEXT: ret i1 %tmp %tmp10 = call i16 @llvm.bswap.i16( i16 %tmp2 ) %tmp = icmp eq i16 %tmp10, 1 ret i1 %tmp } define i1 @test2(i32 %tmp) { +; CHECK-LABEL: @test2 +; CHECK-NEXT: %tmp.upgrd.1 = icmp eq i32 %tmp, 16777216 +; CHECK-NEXT: ret i1 %tmp.upgrd.1 %tmp34 = tail call i32 @llvm.bswap.i32( i32 %tmp ) %tmp.upgrd.1 = icmp eq i32 %tmp34, 1 ret i1 %tmp.upgrd.1 } -declare i32 @llvm.bswap.i32(i32) - define i1 @test3(i64 %tmp) { +; CHECK-LABEL: @test3 +; CHECK-NEXT: %tmp.upgrd.2 = icmp eq i64 %tmp, 72057594037927936 +; CHECK-NEXT: ret i1 %tmp.upgrd.2 %tmp34 = tail call i64 @llvm.bswap.i64( i64 %tmp ) %tmp.upgrd.2 = icmp eq i64 %tmp34, 1 ret i1 %tmp.upgrd.2 } -declare i64 @llvm.bswap.i64(i64) - -declare i16 @llvm.bswap.i16(i16) - ; rdar://5992453 ; A & 255 define i32 @test4(i32 %a) nounwind { -entry: - %tmp2 = tail call i32 @llvm.bswap.i32( i32 %a ) +; CHECK-LABEL: @test4 +; CHECK-NEXT: %tmp2 = and i32 %a, 255 +; CHECK-NEXT: ret i32 %tmp2 + %tmp2 = tail call i32 @llvm.bswap.i32( i32 %a ) %tmp4 = lshr i32 %tmp2, 24 ret i32 %tmp4 } ; A -define i32 @test5(i32 %a) nounwind { -entry: +define i32 @test5(i32 %a) nounwind { +; CHECK-LABEL: @test5 +; CHECK-NEXT: ret i32 %a %tmp2 = tail call i32 @llvm.bswap.i32( i32 %a ) %tmp4 = tail call i32 @llvm.bswap.i32( i32 %tmp2 ) ret i32 %tmp4 } ; a >> 24 -define i32 @test6(i32 %a) nounwind { -entry: - %tmp2 = tail call i32 @llvm.bswap.i32( i32 %a ) +define i32 @test6(i32 %a) nounwind { +; CHECK-LABEL: @test6 +; CHECK-NEXT: %tmp2 = lshr i32 %a, 24 +; CHECK-NEXT ret i32 %tmp4 + %tmp2 = tail call i32 @llvm.bswap.i32( i32 %a ) %tmp4 = and i32 %tmp2, 255 ret i32 %tmp4 } ; PR5284 define i16 @test7(i32 %A) { - %B = tail call i32 @llvm.bswap.i32(i32 %A) nounwind +; CHECK-LABEL: @test7 +; CHECK-NEXT: %1 = lshr i32 %A, 16 +; CHECK-NEXT: %D = trunc i32 %1 to i16 +; CHECK-NEXT ret i16 %D + %B = tail call i32 @llvm.bswap.i32(i32 %A) nounwind %C = trunc i32 %B to i16 %D = tail call i16 @llvm.bswap.i16(i16 %C) nounwind ret i16 %D } define i16 @test8(i64 %A) { +; CHECK-LABEL: @test8 +; CHECK-NEXT: %1 = lshr i64 %A, 48 +; CHECK-NEXT: %D = trunc i64 %1 to i16 +; CHECK-NEXT ret i16 %D %B = tail call i64 @llvm.bswap.i64(i64 %A) nounwind %C = trunc i64 %B to i16 %D = tail call i16 @llvm.bswap.i16(i16 %C) nounwind @@ -66,6 +82,144 @@ define i16 @test8(i64 %A) { ; Misc: Fold bswap(undef) to undef. define i64 @foo() { +; CHECK-LABEL: @foo +; CHECK-NEXT: ret i64 undef %a = call i64 @llvm.bswap.i64(i64 undef) ret i64 %a } + +; PR15782 +; Fold: OP( BSWAP(x), BSWAP(y) ) -> BSWAP( OP(x, y) ) +; Fold: OP( BSWAP(x), CONSTANT ) -> BSWAP( OP(x, BSWAP(CONSTANT) ) ) +define i16 @bs_and16i(i16 %a, i16 %b) #0 { +; CHECK-LABEL: @bs_and16i +; CHECK-NEXT: %1 = and i16 %a, 4391 +; CHECK-NEXT: %2 = call i16 @llvm.bswap.i16(i16 %1) +; CHECK-NEXT: ret i16 %2 + %1 = tail call i16 @llvm.bswap.i16(i16 %a) + %2 = and i16 %1, 10001 + ret i16 %2 +} + +define i16 @bs_and16(i16 %a, i16 %b) #0 { +; CHECK-LABEL: @bs_and16 +; CHECK-NEXT: %1 = and i16 %a, %b +; CHECK-NEXT: %2 = call i16 @llvm.bswap.i16(i16 %1) +; CHECK-NEXT: ret i16 %2 + %tmp1 = tail call i16 @llvm.bswap.i16(i16 %a) + %tmp2 = tail call i16 @llvm.bswap.i16(i16 %b) + %tmp3 = and i16 %tmp1, %tmp2 + ret i16 %tmp3 +} + +define i16 @bs_or16(i16 %a, i16 %b) #0 { +; CHECK-LABEL: @bs_or16 +; CHECK-NEXT: %1 = or i16 %a, %b +; CHECK-NEXT: %2 = call i16 @llvm.bswap.i16(i16 %1) +; CHECK-NEXT: ret i16 %2 + %tmp1 = tail call i16 @llvm.bswap.i16(i16 %a) + %tmp2 = tail call i16 @llvm.bswap.i16(i16 %b) + %tmp3 = or i16 %tmp1, %tmp2 + ret i16 %tmp3 +} + +define i16 @bs_xor16(i16 %a, i16 %b) #0 { +; CHECK-LABEL: @bs_xor16 +; CHECK-NEXT: %1 = xor i16 %a, %b +; CHECK-NEXT: %2 = call i16 @llvm.bswap.i16(i16 %1) +; CHECK-NEXT: ret i16 %2 + %tmp1 = tail call i16 @llvm.bswap.i16(i16 %a) + %tmp2 = tail call i16 @llvm.bswap.i16(i16 %b) + %tmp3 = xor i16 %tmp1, %tmp2 + ret i16 %tmp3 +} + +define i32 @bs_and32i(i32 %a, i32 %b) #0 { +; CHECK-LABEL: @bs_and32i +; CHECK-NEXT: %1 = and i32 %a, -1585053440 +; CHECK-NEXT: %2 = call i32 @llvm.bswap.i32(i32 %1) +; CHECK-NEXT: ret i32 %2 + %tmp1 = tail call i32 @llvm.bswap.i32(i32 %a) + %tmp2 = and i32 %tmp1, 100001 + ret i32 %tmp2 +} + +define i32 @bs_and32(i32 %a, i32 %b) #0 { +; CHECK-LABEL: @bs_and32 +; CHECK-NEXT: %1 = and i32 %a, %b +; CHECK-NEXT: %2 = call i32 @llvm.bswap.i32(i32 %1) +; CHECK-NEXT: ret i32 %2 + %tmp1 = tail call i32 @llvm.bswap.i32(i32 %a) + %tmp2 = tail call i32 @llvm.bswap.i32(i32 %b) + %tmp3 = and i32 %tmp1, %tmp2 + ret i32 %tmp3 +} + +define i32 @bs_or32(i32 %a, i32 %b) #0 { +; CHECK-LABEL: @bs_or32 +; CHECK-NEXT: %1 = or i32 %a, %b +; CHECK-NEXT: %2 = call i32 @llvm.bswap.i32(i32 %1) +; CHECK-NEXT: ret i32 %2 + %tmp1 = tail call i32 @llvm.bswap.i32(i32 %a) + %tmp2 = tail call i32 @llvm.bswap.i32(i32 %b) + %tmp3 = or i32 %tmp1, %tmp2 + ret i32 %tmp3 +} + +define i32 @bs_xor32(i32 %a, i32 %b) #0 { +; CHECK-LABEL: @bs_xor32 +; CHECK-NEXT: %1 = xor i32 %a, %b +; CHECK-NEXT: %2 = call i32 @llvm.bswap.i32(i32 %1) +; CHECK-NEXT: ret i32 %2 + %tmp1 = tail call i32 @llvm.bswap.i32(i32 %a) + %tmp2 = tail call i32 @llvm.bswap.i32(i32 %b) + %tmp3 = xor i32 %tmp1, %tmp2 + ret i32 %tmp3 +} + +define i64 @bs_and64i(i64 %a, i64 %b) #0 { +; CHECK-LABEL: @bs_and64i +; CHECK-NEXT: %1 = and i64 %a, 129085117527228416 +; CHECK-NEXT: %2 = call i64 @llvm.bswap.i64(i64 %1) +; CHECK-NEXT: ret i64 %2 + %tmp1 = tail call i64 @llvm.bswap.i64(i64 %a) + %tmp2 = and i64 %tmp1, 1000000001 + ret i64 %tmp2 +} + +define i64 @bs_and64(i64 %a, i64 %b) #0 { +; CHECK-LABEL: @bs_and64 +; CHECK-NEXT: %1 = and i64 %a, %b +; CHECK-NEXT: %2 = call i64 @llvm.bswap.i64(i64 %1) +; CHECK-NEXT: ret i64 %2 + %tmp1 = tail call i64 @llvm.bswap.i64(i64 %a) + %tmp2 = tail call i64 @llvm.bswap.i64(i64 %b) + %tmp3 = and i64 %tmp1, %tmp2 + ret i64 %tmp3 +} + +define i64 @bs_or64(i64 %a, i64 %b) #0 { +; CHECK-LABEL: @bs_or64 +; CHECK-NEXT: %1 = or i64 %a, %b +; CHECK-NEXT: %2 = call i64 @llvm.bswap.i64(i64 %1) +; CHECK-NEXT: ret i64 %2 + %tmp1 = tail call i64 @llvm.bswap.i64(i64 %a) + %tmp2 = tail call i64 @llvm.bswap.i64(i64 %b) + %tmp3 = or i64 %tmp1, %tmp2 + ret i64 %tmp3 +} + +define i64 @bs_xor64(i64 %a, i64 %b) #0 { +; CHECK-LABEL: @bs_xor64 +; CHECK-NEXT: %1 = xor i64 %a, %b +; CHECK-NEXT: %2 = call i64 @llvm.bswap.i64(i64 %1) +; CHECK-NEXT: ret i64 %2 + %tmp1 = tail call i64 @llvm.bswap.i64(i64 %a) + %tmp2 = tail call i64 @llvm.bswap.i64(i64 %b) + %tmp3 = xor i64 %tmp1, %tmp2 + ret i64 %tmp3 +} + +declare i16 @llvm.bswap.i16(i16) +declare i32 @llvm.bswap.i32(i32) +declare i64 @llvm.bswap.i64(i64) diff --git a/test/Transforms/InstCombine/call-cast-target.ll b/test/Transforms/InstCombine/call-cast-target.ll index 1af3317a398b..b82dd99db36f 100644 --- a/test/Transforms/InstCombine/call-cast-target.ll +++ b/test/Transforms/InstCombine/call-cast-target.ll @@ -5,7 +5,9 @@ target triple = "i686-pc-linux-gnu" define i32 @main() { ; CHECK-LABEL: @main -; CHECK: call i32 bitcast +; CHECK: %[[call:.*]] = call i8* @ctime(i32* null) +; CHECK: %[[cast:.*]] = ptrtoint i8* %[[call]] to i32 +; CHECK: ret i32 %[[cast]] entry: %tmp = call i32 bitcast (i8* (i32*)* @ctime to i32 (i32*)*)( i32* null ) ; <i32> [#uses=1] ret i32 %tmp @@ -25,3 +27,37 @@ entry: %0 = call { i8 } bitcast ({ i8 } (i32*)* @foo to { i8 } (i16*)*)(i16* null) ret void } + +declare i32 @fn1(i32) + +define i32 @test1(i32* %a) { +; CHECK-LABEL: @test1 +; CHECK: %[[cast:.*]] = ptrtoint i32* %a to i32 +; CHECK-NEXT: %[[call:.*]] = tail call i32 @fn1(i32 %[[cast]]) +; CHECK-NEXT: ret i32 %[[call]] +entry: + %call = tail call i32 bitcast (i32 (i32)* @fn1 to i32 (i32*)*)(i32* %a) + ret i32 %call +} + +declare i32 @fn2(i16) + +define i32 @test2(i32* %a) { +; CHECK-LABEL: @test2 +; CHECK: %[[call:.*]] = tail call i32 bitcast (i32 (i16)* @fn2 to i32 (i32*)*)(i32* %a) +; CHECK-NEXT: ret i32 %[[call]] +entry: + %call = tail call i32 bitcast (i32 (i16)* @fn2 to i32 (i32*)*)(i32* %a) + ret i32 %call +} + +declare i32 @fn3(i64) + +define i32 @test3(i32* %a) { +; CHECK-LABEL: @test3 +; CHECK: %[[call:.*]] = tail call i32 bitcast (i32 (i64)* @fn3 to i32 (i32*)*)(i32* %a) +; CHECK-NEXT: ret i32 %[[call]] +entry: + %call = tail call i32 bitcast (i32 (i64)* @fn3 to i32 (i32*)*)(i32* %a) + ret i32 %call +} diff --git a/test/Transforms/InstCombine/canonicalize_branch.ll b/test/Transforms/InstCombine/canonicalize_branch.ll index b62b143d9d51..29fd51a39ab4 100644 --- a/test/Transforms/InstCombine/canonicalize_branch.ll +++ b/test/Transforms/InstCombine/canonicalize_branch.ll @@ -57,10 +57,10 @@ F: ret i32 123 } -!0 = metadata !{metadata !"branch_weights", i32 1, i32 2} -!1 = metadata !{metadata !"branch_weights", i32 3, i32 4} -!2 = metadata !{metadata !"branch_weights", i32 5, i32 6} -!3 = metadata !{metadata !"branch_weights", i32 7, i32 8} +!0 = !{!"branch_weights", i32 1, i32 2} +!1 = !{!"branch_weights", i32 3, i32 4} +!2 = !{!"branch_weights", i32 5, i32 6} +!3 = !{!"branch_weights", i32 7, i32 8} ; Base case shouldn't change. ; CHECK: !0 = {{.*}} i32 1, i32 2} ; Ensure that the branch metadata is reversed to match the reversals above. diff --git a/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll b/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll new file mode 100644 index 000000000000..551d0efce5ea --- /dev/null +++ b/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll @@ -0,0 +1,454 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_0_uitofp( +; CHECK-NEXT: icmp eq i32 %i, 0 +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_0_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp oeq float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_n0_uitofp( +; CHECK: uitofp +; CHECK: fcmp oeq +define i1 @i32_cast_cmp_oeq_int_n0_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp oeq float %f, -0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_0_sitofp( +; CHECK-NEXT: icmp eq i32 %i, 0 +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_0_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp oeq float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_n0_sitofp( +; CHECK: sitofp +; CHECK: fcmp oeq +define i1 @i32_cast_cmp_oeq_int_n0_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp oeq float %f, -0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_one_int_0_uitofp( +; CHECK-NEXT: icmp ne i32 %i, 0 +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_one_int_0_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp one float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_one_int_n0_uitofp( +; CHECK: uitofp +; CHECK: fcmp one +define i1 @i32_cast_cmp_one_int_n0_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp one float %f, -0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_one_int_0_sitofp( +; CHECK-NEXT: icmp ne i32 %i, 0 +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_one_int_0_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp one float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_one_int_n0_sitofp( +; CHECK: sitofp +; CHECK: fcmp one +define i1 @i32_cast_cmp_one_int_n0_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp one float %f, -0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_ueq_int_0_uitofp( +; CHECK-NEXT: icmp eq i32 %i, 0 +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_ueq_int_0_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp ueq float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_ueq_int_n0_uitofp( +; CHECK: uitofp +; CHECK: fcmp ueq +define i1 @i32_cast_cmp_ueq_int_n0_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp ueq float %f, -0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_ueq_int_0_sitofp( +; CHECK-NEXT: icmp eq i32 %i, 0 +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_ueq_int_0_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp ueq float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_ueq_int_n0_sitofp( +; CHECK: sitofp +; CHECK: fcmp ueq +define i1 @i32_cast_cmp_ueq_int_n0_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp ueq float %f, -0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_une_int_0_uitofp( +; CHECK-NEXT: icmp ne i32 %i, 0 +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_une_int_0_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp une float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_une_int_n0_uitofp( +; CHECK: uitofp +; CHECK: fcmp une +define i1 @i32_cast_cmp_une_int_n0_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp une float %f, -0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_une_int_0_sitofp( +; CHECK-NEXT: icmp ne i32 %i, 0 +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_une_int_0_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp une float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_une_int_n0_sitofp( +; CHECK: sitofp +; CHECK: fcmp une +define i1 @i32_cast_cmp_une_int_n0_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp une float %f, -0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_ogt_int_0_uitofp( +; CHECK: icmp ne i32 %i, 0 +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_ogt_int_0_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp ogt float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_ogt_int_n0_uitofp( +; CHECK: uitofp +; CHECK: fcmp ogt +define i1 @i32_cast_cmp_ogt_int_n0_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp ogt float %f, -0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_ogt_int_0_sitofp( +; CHECK: icmp sgt i32 %i, 0 +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_ogt_int_0_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp ogt float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_ogt_int_n0_sitofp( +; CHECK: sitofp +; CHECK: fcmp ogt +define i1 @i32_cast_cmp_ogt_int_n0_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp ogt float %f, -0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_ole_int_0_uitofp( +; CHECK: icmp eq i32 %i, 0 +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_ole_int_0_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp ole float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_ole_int_0_sitofp( +; CHECK: icmp slt i32 %i, 1 +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_ole_int_0_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp ole float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_olt_int_0_uitofp( +; CHECK: ret i1 false +define i1 @i32_cast_cmp_olt_int_0_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp olt float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_olt_int_0_sitofp( +; CHECK: icmp slt i32 %i, 0 +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_olt_int_0_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp olt float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i64_cast_cmp_oeq_int_0_uitofp( +; CHECK-NEXT: icmp eq i64 %i, 0 +; CHECK-NEXT: ret +define i1 @i64_cast_cmp_oeq_int_0_uitofp(i64 %i) { + %f = uitofp i64 %i to float + %cmp = fcmp oeq float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i64_cast_cmp_oeq_int_0_sitofp( +; CHECK-NEXT: icmp eq i64 %i, 0 +; CHECK-NEXT: ret +define i1 @i64_cast_cmp_oeq_int_0_sitofp(i64 %i) { + %f = sitofp i64 %i to float + %cmp = fcmp oeq float %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i64_cast_cmp_oeq_int_0_uitofp_half( +; CHECK-NEXT: icmp eq i64 %i, 0 +; CHECK-NEXT: ret +define i1 @i64_cast_cmp_oeq_int_0_uitofp_half(i64 %i) { + %f = uitofp i64 %i to half + %cmp = fcmp oeq half %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i64_cast_cmp_oeq_int_0_sitofp_half( +; CHECK-NEXT: icmp eq i64 %i, 0 +; CHECK-NEXT: ret +define i1 @i64_cast_cmp_oeq_int_0_sitofp_half(i64 %i) { + %f = sitofp i64 %i to half + %cmp = fcmp oeq half %f, 0.0 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_0_uitofp_ppcf128( +; CHECK: uitofp +; CHECK: fcmp oeq +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_0_uitofp_ppcf128(i32 %i) { + %f = uitofp i32 %i to ppc_fp128 + %cmp = fcmp oeq ppc_fp128 %f, 0xM00000000000000000000000000000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24max_uitofp( +; CHECK: uitofp +; CHECK: fcmp oeq + +; XCHECK: icmp eq i32 %i, 16777215 +; XCHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_i24max_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp oeq float %f, 0x416FFFFFE0000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24max_sitofp( +; CHECK: sitofp +; CHECK: fcmp oeq + +; XCHECK: icmp eq i32 %i, 16777215 +; XCHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_i24max_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp oeq float %f, 0x416FFFFFE0000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24maxp1_uitofp( +; CHECK: uitofp +; CHECK: fcmp oeq + +; XCHECK: icmp eq i32 %i, 16777216 +; XCHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_i24maxp1_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp oeq float %f, 0x4170000000000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24maxp1_sitofp( +; CHECK: sitofp +; CHECK: fcmp oeq + +; XCHECK: icmp eq i32 %i, 16777216 +; XCHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_i24maxp1_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp oeq float %f, 0x4170000000000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_i32umax_uitofp( +; CHECK: uitofp +; CHECK: fcmp oeq +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_i32umax_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp oeq float %f, 0x41F0000000000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_i32umax_sitofp( +; CHECK: sitofp +; CHECK: fcmp oeq +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_i32umax_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp oeq float %f, 0x41F0000000000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_i32imin_uitofp( +; CHECK: uitofp +; CHECK: fcmp oeq +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_i32imin_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp oeq float %f, 0xC1E0000000000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_i32imin_sitofp( +; CHECK: sitofp +; CHECK: fcmp oeq +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_i32imin_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp oeq float %f, 0xC1E0000000000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_i32imax_uitofp( +; CHECK: uitofp +; CHECK: fcmp oeq +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_i32imax_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp oeq float %f, 0x41E0000000000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_i32imax_sitofp( +; CHECK: sitofp +; CHECK: fcmp oeq +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_i32imax_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp oeq float %f, 0x41E0000000000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_negi32umax_uitofp( +; CHECK: uitofp +; CHECK: fcmp oeq +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_negi32umax_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp oeq float %f, 0xC1F0000000000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_negi32umax_sitofp( +; CHECK: sitofp +; CHECK: fcmp oeq +; CHECK-NEXT: ret +define i1 @i32_cast_cmp_oeq_int_negi32umax_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp oeq float %f, 0xC1F0000000000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_half_uitofp( +; CHECK: ret i1 false +define i1 @i32_cast_cmp_oeq_half_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp oeq float %f, 0.5 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_half_sitofp( +; CHECK: ret i1 false +define i1 @i32_cast_cmp_oeq_half_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp oeq float %f, 0.5 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_one_half_uitofp( +; CHECK: ret i1 true +define i1 @i32_cast_cmp_one_half_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp one float %f, 0.5 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_one_half_sitofp( +; CHECK: ret i1 true +define i1 @i32_cast_cmp_one_half_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp one float %f, 0.5 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_ueq_half_uitofp( +; CHECK: ret i1 false +define i1 @i32_cast_cmp_ueq_half_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp ueq float %f, 0.5 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_ueq_half_sitofp( +; CHECK: ret i1 false +define i1 @i32_cast_cmp_ueq_half_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp ueq float %f, 0.5 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_une_half_uitofp( +; CHECK: ret i1 true +define i1 @i32_cast_cmp_une_half_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp une float %f, 0.5 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_une_half_sitofp( +; CHECK: ret i1 true +define i1 @i32_cast_cmp_une_half_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp une float %f, 0.5 + ret i1 %cmp +} diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll index 0cbfbb071bb7..aac7a531b356 100644 --- a/test/Transforms/InstCombine/cast.ll +++ b/test/Transforms/InstCombine/cast.ll @@ -99,6 +99,26 @@ define void @test11(i32* %P) { ; CHECK: ret void } +declare i32 @__gxx_personality_v0(...) +define void @test_invoke_vararg_cast(i32* %a, i32* %b) { +entry: + %0 = bitcast i32* %b to i8* + %1 = bitcast i32* %a to i64* + invoke void (i32, ...)* @varargs(i32 1, i8* %0, i64* %1) + to label %invoke.cont unwind label %lpad + +invoke.cont: ; preds = %entry + ret void + +lpad: ; preds = %entry + %2 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup + ret void +; CHECK-LABEL: test_invoke_vararg_cast +; CHECK-LABEL: entry: +; CHECK: invoke void (i32, ...)* @varargs(i32 1, i32* %b, i32* %a) +} + define i8* @test13(i64 %A) { %c = getelementptr [0 x i8]* bitcast ([32832 x i8]* @inbuf to [0 x i8]*), i64 0, i64 %A ; <i8*> [#uses=1] ret i8* %c @@ -199,15 +219,6 @@ define i1 @test24(i1 %C) { ; CHECK: ret i1 true } -define void @test25(i32** %P) { - %c = bitcast i32** %P to float** ; <float**> [#uses=1] - ;; Fold cast into null - store float* null, float** %c - ret void -; CHECK: store i32* null, i32** %P -; CHECK: ret void -} - define i32 @test26(float %F) { ;; no need to cast from float->double. %c = fpext float %F to double ; <double> [#uses=1] @@ -354,6 +365,24 @@ define i32* @test41(i32* %tmp1) { ; CHECK: ret i32* %tmp1 } +define i32 addrspace(1)* @test41_addrspacecast_smaller(i32* %tmp1) { + %tmp64 = addrspacecast i32* %tmp1 to { i32 } addrspace(1)* + %tmp65 = getelementptr { i32 } addrspace(1)* %tmp64, i32 0, i32 0 + ret i32 addrspace(1)* %tmp65 +; CHECK-LABEL: @test41_addrspacecast_smaller( +; CHECK: addrspacecast i32* %tmp1 to i32 addrspace(1)* +; CHECK-NEXT: ret i32 addrspace(1)* +} + +define i32* @test41_addrspacecast_larger(i32 addrspace(1)* %tmp1) { + %tmp64 = addrspacecast i32 addrspace(1)* %tmp1 to { i32 }* + %tmp65 = getelementptr { i32 }* %tmp64, i32 0, i32 0 + ret i32* %tmp65 +; CHECK-LABEL: @test41_addrspacecast_larger( +; CHECK: addrspacecast i32 addrspace(1)* %tmp1 to i32* +; CHECK-NEXT: ret i32* +} + define i32 @test42(i32 %X) { %Y = trunc i32 %X to i8 ; <i8> [#uses=1] %Z = zext i8 %Y to i32 ; <i32> [#uses=1] @@ -792,7 +821,7 @@ define double @test71(double *%p, i64 %i) { define double @test72(double *%p, i32 %i) { ; CHECK-LABEL: @test72( - %so = mul nsw i32 %i, 8 + %so = shl nsw i32 %i, 3 %o = sext i32 %so to i64 ; CHECK-NEXT: sext i32 %i to i64 %q = bitcast double* %p to i8* @@ -807,7 +836,7 @@ define double @test72(double *%p, i32 %i) { define double @test73(double *%p, i128 %i) { ; CHECK-LABEL: @test73( - %lo = mul nsw i128 %i, 8 + %lo = shl nsw i128 %i, 3 %o = trunc i128 %lo to i64 ; CHECK-NEXT: trunc i128 %i to i64 %q = bitcast double* %p to i8* @@ -919,7 +948,7 @@ define %s @test79(%s *%p, i64 %i, i32 %j) { define double @test80([100 x double]* %p, i32 %i) { ; CHECK-LABEL: @test80( - %tmp = mul nsw i32 %i, 8 + %tmp = shl nsw i32 %i, 3 ; CHECK-NEXT: sext i32 %i to i64 %q = bitcast [100 x double]* %p to i8* %pp = getelementptr i8* %q, i32 %tmp @@ -936,7 +965,7 @@ define double @test80_addrspacecast([100 x double] addrspace(1)* %p, i32 %i) { ; CHECK-NEXT: getelementptr [100 x double] addrspace(1)* %p ; CHECK-NEXT: load double addrspace(1)* ; CHECK-NEXT: ret double - %tmp = mul nsw i32 %i, 8 + %tmp = shl nsw i32 %i, 3 %q = addrspacecast [100 x double] addrspace(1)* %p to i8 addrspace(2)* %pp = getelementptr i8 addrspace(2)* %q, i32 %tmp %r = addrspacecast i8 addrspace(2)* %pp to double addrspace(1)* @@ -950,7 +979,7 @@ define double @test80_addrspacecast_2([100 x double] addrspace(1)* %p, i32 %i) { ; CHECK-NEXT: addrspacecast double addrspace(1)* ; CHECK-NEXT: load double addrspace(3)* ; CHECK-NEXT: ret double - %tmp = mul nsw i32 %i, 8 + %tmp = shl nsw i32 %i, 3 %q = addrspacecast [100 x double] addrspace(1)* %p to i8 addrspace(2)* %pp = getelementptr i8 addrspace(2)* %q, i32 %tmp %r = addrspacecast i8 addrspace(2)* %pp to double addrspace(3)* @@ -960,7 +989,7 @@ define double @test80_addrspacecast_2([100 x double] addrspace(1)* %p, i32 %i) { define double @test80_as1([100 x double] addrspace(1)* %p, i16 %i) { ; CHECK-LABEL: @test80_as1( - %tmp = mul nsw i16 %i, 8 + %tmp = shl nsw i16 %i, 3 ; CHECK-NEXT: sext i16 %i to i32 %q = bitcast [100 x double] addrspace(1)* %p to i8 addrspace(1)* %pp = getelementptr i8 addrspace(1)* %q, i16 %tmp @@ -1004,7 +1033,74 @@ define i64 @test83(i16 %a, i64 %k) { ret i64 %sh_prom1 ; CHECK-LABEL: @test83( -; CHECK: %sub = add nsw i64 %k, 4294967295 +; CHECK: %sub = add i64 %k, 4294967295 ; CHECK: %sh_prom = trunc i64 %sub to i32 ; CHECK: %shl = shl i32 %conv, %sh_prom } + +define i8 @test84(i32 %a) { + %add = add nsw i32 %a, -16777216 + %shr = lshr exact i32 %add, 23 + %trunc = trunc i32 %shr to i8 + ret i8 %trunc + +; CHECK-LABEL: @test84( +; CHECK: [[ADD:%.*]] = add i32 %a, 2130706432 +; CHECK: [[SHR:%.*]] = lshr exact i32 [[ADD]], 23 +; CHECK: [[CST:%.*]] = trunc i32 [[SHR]] to i8 +} + +define i8 @test85(i32 %a) { + %add = add nuw i32 %a, -16777216 + %shr = lshr exact i32 %add, 23 + %trunc = trunc i32 %shr to i8 + ret i8 %trunc + +; CHECK-LABEL: @test85( +; CHECK: [[ADD:%.*]] = add i32 %a, 2130706432 +; CHECK: [[SHR:%.*]] = lshr exact i32 [[ADD]], 23 +; CHECK: [[CST:%.*]] = trunc i32 [[SHR]] to i8 +} + +; Overflow on a float to int or int to float conversion is undefined (PR21130). + +define i8 @overflow_fptosi() { + %i = fptosi double 1.56e+02 to i8 + ret i8 %i +; CHECK-LABEL: @overflow_fptosi( +; CHECK-NEXT: ret i8 undef +} + +define i8 @overflow_fptoui() { + %i = fptoui double 2.56e+02 to i8 + ret i8 %i +; CHECK-LABEL: @overflow_fptoui( +; CHECK-NEXT: ret i8 undef +} + +; The maximum float is approximately 2 ** 128 which is 3.4E38. +; The constant below is 4E38. Use a 130 bit integer to hold that +; number; 129-bits for the value + 1 bit for the sign. +define float @overflow_uitofp() { + %i = uitofp i130 400000000000000000000000000000000000000 to float + ret float %i +; CHECK-LABEL: @overflow_uitofp( +; CHECK-NEXT: ret float undef +} + +define float @overflow_sitofp() { + %i = sitofp i130 400000000000000000000000000000000000000 to float + ret float %i +; CHECK-LABEL: @overflow_sitofp( +; CHECK-NEXT: ret float undef +} + +define i32 @PR21388(i32* %v) { + %icmp = icmp slt i32* %v, null + %sext = sext i1 %icmp to i32 + ret i32 %sext +; CHECK-LABEL: @PR21388( +; CHECK-NEXT: %[[icmp:.*]] = icmp slt i32* %v, null +; CHECK-NEXT: %[[sext:.*]] = sext i1 %[[icmp]] to i32 +; CHECK-NEXT: ret i32 %[[sext]] +} diff --git a/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll b/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll index 7fac78a40f56..bb61f02c8e23 100644 --- a/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll +++ b/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll @@ -161,12 +161,11 @@ define i32 @constant_fold_bitcast_itof_load() { ret i32 %a } -define <4 x i32> @constant_fold_bitcast_vector_as() { +define <4 x float> @constant_fold_bitcast_vector_as() { ; CHECK-LABEL: @constant_fold_bitcast_vector_as( ; CHECK: load <4 x float> addrspace(3)* @g_v4f_as3, align 16 -; CHECK: bitcast <4 x float> %1 to <4 x i32> - %a = load <4 x i32> addrspace(3)* bitcast (<4 x float> addrspace(3)* @g_v4f_as3 to <4 x i32> addrspace(3)*), align 4 - ret <4 x i32> %a + %a = load <4 x float> addrspace(3)* bitcast (<4 x i32> addrspace(3)* bitcast (<4 x float> addrspace(3)* @g_v4f_as3 to <4 x i32> addrspace(3)*) to <4 x float> addrspace(3)*), align 4 + ret <4 x float> %a } @i32_array_as3 = addrspace(3) global [10 x i32] zeroinitializer diff --git a/test/Transforms/InstCombine/constant-fold-alias.ll b/test/Transforms/InstCombine/constant-fold-alias.ll new file mode 100644 index 000000000000..13da0f445242 --- /dev/null +++ b/test/Transforms/InstCombine/constant-fold-alias.ll @@ -0,0 +1,40 @@ +; RUN: opt -S < %s -instcombine | FileCheck %s + +target datalayout = "e-p1:16:16-p2:32:32-p3:64:64" + +@G1 = global i32 42, align 1 +@G2 = global i32 42 +@G3 = global [4 x i8] zeroinitializer, align 1 + +@A1 = alias bitcast (i8* getelementptr inbounds ([4 x i8]* @G3, i32 0, i32 2) to i32*) +@A2 = alias inttoptr (i64 and (i64 ptrtoint (i8* getelementptr inbounds ([4 x i8]* @G3, i32 0, i32 3) to i64), i64 -4) to i32*) + +define i64 @f1() { +; This cannot be constant folded because G1 is underaligned. +; CHECK-LABEL: @f1( +; CHECK: ret i64 and + ret i64 and (i64 ptrtoint (i32* @G1 to i64), i64 1) +} + +define i64 @f2() { +; The preferred alignment for G2 allows this one to foled to zero. +; CHECK-LABEL: @f2( +; CHECK: ret i64 0 + ret i64 and (i64 ptrtoint (i32* @G2 to i64), i64 1) +} + +define i64 @g1() { +; This cannot be constant folded because A1 aliases G3 which is underalaigned. +; CHECK-LABEL: @g1( +; CHECK: ret i64 and + ret i64 and (i64 ptrtoint (i32* @A1 to i64), i64 1) +} + +define i64 @g2() { +; While A2 also aliases G3 which is underaligned, the math of A2 forces a +; certain alignment allowing this to fold to zero. +; CHECK-LABEL: @g2( +; CHECK: ret i64 0 + ret i64 and (i64 ptrtoint (i32* @A2 to i64), i64 1) +} + diff --git a/test/Transforms/InstCombine/constant-fold-math.ll b/test/Transforms/InstCombine/constant-fold-math.ll index 14377df37299..ce8d337c08bf 100644 --- a/test/Transforms/InstCombine/constant-fold-math.ll +++ b/test/Transforms/InstCombine/constant-fold-math.ll @@ -7,6 +7,7 @@ declare <4 x float> @llvm.fma.v4f32(<4 x float>, <4 x float>, <4 x float>) #0 declare double @llvm.fma.f64(double, double, double) #0 declare double @llvm.fmuladd.f64(double, double, double) #0 +declare double @llvm.sqrt.f64(double) #0 ; CHECK-LABEL: @constant_fold_fma_f32 @@ -44,4 +45,12 @@ define double @constant_fold_fmuladd_f64() #0 { ret double %x } +; The sqrt intrinsic is undefined for negative inputs besides -0.0. +; CHECK-LABEL: @bad_sqrt +; CHECK-NEXT: ret double undef +define double @bad_sqrt() { + %x = call double @llvm.sqrt.f64(double -2.000000e+00) + ret double %x +} + attributes #0 = { nounwind readnone } diff --git a/test/Transforms/InstCombine/debug-line.ll b/test/Transforms/InstCombine/debug-line.ll index 2e3785fe597e..1946576183c4 100644 --- a/test/Transforms/InstCombine/debug-line.ll +++ b/test/Transforms/InstCombine/debug-line.ll @@ -15,14 +15,14 @@ declare i32 @printf(i8*, ...) !llvm.module.flags = !{!10} !llvm.dbg.sp = !{!0} -!0 = metadata !{i32 589870, metadata !8, metadata !1, metadata !"foo", metadata !"foo", metadata !"", i32 4, metadata !3, i1 false, i1 true, i32 0, i32 0, null, i32 0, i1 false, void ()* @foo, null, null, null, i32 0} ; [ DW_TAG_subprogram ] -!1 = metadata !{i32 589865, metadata !8} ; [ DW_TAG_file_type ] -!2 = metadata !{i32 589841, metadata !8, i32 12, metadata !"clang", i1 true, metadata !"", i32 0, metadata !4, metadata !4, metadata !9, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!3 = metadata !{i32 589845, metadata !8, metadata !1, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !4, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!4 = metadata !{null} -!5 = metadata !{i32 5, i32 2, metadata !6, null} -!6 = metadata !{i32 589835, metadata !8, metadata !0, i32 4, i32 12, i32 0} ; [ DW_TAG_lexical_block ] -!7 = metadata !{i32 6, i32 1, metadata !6, null} -!8 = metadata !{metadata !"m.c", metadata !"/private/tmp"} -!9 = metadata !{metadata !0} -!10 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x2e\00foo\00foo\00\004\000\001\000\006\000\000\000", !8, !1, !3, null, void ()* @foo, null, null, null} ; [ DW_TAG_subprogram ] +!1 = !{!"0x29", !8} ; [ DW_TAG_file_type ] +!2 = !{!"0x11\0012\00clang\001\00\000\00\000", !8, !4, !4, !9, null, null} ; [ DW_TAG_compile_unit ] +!3 = !{!"0x15\00\000\000\000\000\000\000", !8, !1, null, !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!4 = !{null} +!5 = !MDLocation(line: 5, column: 2, scope: !6) +!6 = !{!"0xb\004\0012\000", !8, !0} ; [ DW_TAG_lexical_block ] +!7 = !MDLocation(line: 6, column: 1, scope: !6) +!8 = !{!"m.c", !"/private/tmp"} +!9 = !{!0} +!10 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/InstCombine/debuginfo.ll b/test/Transforms/InstCombine/debuginfo.ll index 75082dcae055..ae72f700039e 100644 --- a/test/Transforms/InstCombine/debuginfo.ll +++ b/test/Transforms/InstCombine/debuginfo.ll @@ -1,6 +1,6 @@ ; RUN: opt < %s -instcombine -S | FileCheck %s -declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) nounwind readnone @@ -14,11 +14,11 @@ entry: store i8* %__dest, i8** %__dest.addr, align 8 ; CHECK-NOT: call void @llvm.dbg.declare ; CHECK: call void @llvm.dbg.value - call void @llvm.dbg.declare(metadata !{i8** %__dest.addr}, metadata !0), !dbg !16 + call void @llvm.dbg.declare(metadata i8** %__dest.addr, metadata !0, metadata !{}), !dbg !16 store i32 %__val, i32* %__val.addr, align 4 - call void @llvm.dbg.declare(metadata !{i32* %__val.addr}, metadata !7), !dbg !18 + call void @llvm.dbg.declare(metadata i32* %__val.addr, metadata !7, metadata !{}), !dbg !18 store i64 %__len, i64* %__len.addr, align 8 - call void @llvm.dbg.declare(metadata !{i64* %__len.addr}, metadata !9), !dbg !20 + call void @llvm.dbg.declare(metadata i64* %__len.addr, metadata !9, metadata !{}), !dbg !20 %tmp = load i8** %__dest.addr, align 8, !dbg !21 %tmp1 = load i32* %__val.addr, align 4, !dbg !21 %tmp2 = load i64* %__len.addr, align 8, !dbg !21 @@ -31,29 +31,29 @@ entry: !llvm.dbg.cu = !{!3} !llvm.module.flags = !{!30} -!0 = metadata !{i32 786689, metadata !1, metadata !"__dest", metadata !2, i32 16777294, metadata !6, i32 0, null} ; [ DW_TAG_arg_variable ] -!1 = metadata !{i32 786478, metadata !27, metadata !2, metadata !"foobar", metadata !"foobar", metadata !"", i32 79, metadata !4, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 true, i8* (i8*, i32, i64)* @foobar, null, null, metadata !25, i32 79} ; [ DW_TAG_subprogram ] [line 79] [local] [def] [foobar] -!2 = metadata !{i32 786473, metadata !27} ; [ DW_TAG_file_type ] -!3 = metadata !{i32 786449, metadata !28, i32 12, metadata !"clang version 3.0 (trunk 127710)", i1 true, metadata !"", i32 0, metadata !29, metadata !29, metadata !24, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!4 = metadata !{i32 786453, metadata !27, metadata !2, metadata !"", i32 0, i64 0, i64 0, i32 0, i32 0, null, metadata !5, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!5 = metadata !{metadata !6} -!6 = metadata !{i32 786447, null, metadata !3, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, null} ; [ DW_TAG_pointer_type ] -!7 = metadata !{i32 786689, metadata !1, metadata !"__val", metadata !2, i32 33554510, metadata !8, i32 0, null} ; [ DW_TAG_arg_variable ] -!8 = metadata !{i32 786468, null, metadata !3, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!9 = metadata !{i32 786689, metadata !1, metadata !"__len", metadata !2, i32 50331726, metadata !10, i32 0, null} ; [ DW_TAG_arg_variable ] -!10 = metadata !{i32 589846, metadata !27, metadata !3, metadata !"size_t", i32 80, i64 0, i64 0, i64 0, i32 0, metadata !11} ; [ DW_TAG_typedef ] -!11 = metadata !{i32 589846, metadata !27, metadata !3, metadata !"__darwin_size_t", i32 90, i64 0, i64 0, i64 0, i32 0, metadata !12} ; [ DW_TAG_typedef ] -!12 = metadata !{i32 786468, null, metadata !3, metadata !"long unsigned int", i32 0, i64 64, i64 64, i64 0, i32 0, i32 7} ; [ DW_TAG_base_type ] -!16 = metadata !{i32 78, i32 28, metadata !1, null} -!18 = metadata !{i32 78, i32 40, metadata !1, null} -!20 = metadata !{i32 78, i32 54, metadata !1, null} -!21 = metadata !{i32 80, i32 3, metadata !22, null} -!22 = metadata !{i32 786443, metadata !27, metadata !23, i32 80, i32 3, i32 7} ; [ DW_TAG_lexical_block ] -!23 = metadata !{i32 786443, metadata !27, metadata !1, i32 79, i32 1, i32 6} ; [ DW_TAG_lexical_block ] -!24 = metadata !{metadata !1} -!25 = metadata !{metadata !0, metadata !7, metadata !9} -!26 = metadata !{i32 786473, metadata !28} ; [ DW_TAG_file_type ] -!27 = metadata !{metadata !"string.h", metadata !"Game"} -!28 = metadata !{metadata !"bits.c", metadata !"Game"} -!29 = metadata !{i32 0} -!30 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x101\00__dest\0016777294\000", !1, !2, !6} ; [ DW_TAG_arg_variable ] +!1 = !{!"0x2e\00foobar\00foobar\00\0079\001\001\000\006\00256\001\0079", !27, !2, !4, null, i8* (i8*, i32, i64)* @foobar, null, null, !25} ; [ DW_TAG_subprogram ] [line 79] [local] [def] [foobar] +!2 = !{!"0x29", !27} ; [ DW_TAG_file_type ] +!3 = !{!"0x11\0012\00clang version 3.0 (trunk 127710)\001\00\000\00\000", !28, !29, !29, !24, null, null} ; [ DW_TAG_compile_unit ] +!4 = !{!"0x15\00\000\000\000\000\000\000", !27, !2, null, !5, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!5 = !{!6} +!6 = !{!"0xf\00\000\0064\0064\000\000", null, !3, null} ; [ DW_TAG_pointer_type ] +!7 = !{!"0x101\00__val\0033554510\000", !1, !2, !8} ; [ DW_TAG_arg_variable ] +!8 = !{!"0x24\00int\000\0032\0032\000\000\005", null, !3} ; [ DW_TAG_base_type ] +!9 = !{!"0x101\00__len\0050331726\000", !1, !2, !10} ; [ DW_TAG_arg_variable ] +!10 = !{!"0x16\00size_t\0080\000\000\000\000", !27, !3, !11} ; [ DW_TAG_typedef ] +!11 = !{!"0x16\00__darwin_size_t\0090\000\000\000\000", !27, !3, !12} ; [ DW_TAG_typedef ] +!12 = !{!"0x24\00long unsigned int\000\0064\0064\000\000\007", null, !3} ; [ DW_TAG_base_type ] +!16 = !MDLocation(line: 78, column: 28, scope: !1) +!18 = !MDLocation(line: 78, column: 40, scope: !1) +!20 = !MDLocation(line: 78, column: 54, scope: !1) +!21 = !MDLocation(line: 80, column: 3, scope: !22) +!22 = !{!"0xb\0080\003\007", !27, !23} ; [ DW_TAG_lexical_block ] +!23 = !{!"0xb\0079\001\006", !27, !1} ; [ DW_TAG_lexical_block ] +!24 = !{!1} +!25 = !{!0, !7, !9} +!26 = !{!"0x29", !28} ; [ DW_TAG_file_type ] +!27 = !{!"string.h", !"Game"} +!28 = !{!"bits.c", !"Game"} +!29 = !{i32 0} +!30 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/InstCombine/descale-zero.ll b/test/Transforms/InstCombine/descale-zero.ll index 7990fdb3eca3..4656837cc05e 100644 --- a/test/Transforms/InstCombine/descale-zero.ll +++ b/test/Transforms/InstCombine/descale-zero.ll @@ -5,8 +5,7 @@ target triple = "x86_64-apple-macosx10.10.0" define internal i8* @descale_zero() { entry: -; CHECK: load i16** inttoptr (i64 48 to i16**), align 16 -; CHECK-NEXT: bitcast i16* +; CHECK: load i8** inttoptr (i64 48 to i8**), align 16 ; CHECK-NEXT: ret i8* %i16_ptr = load i16** inttoptr (i64 48 to i16**), align 16 %num = load i64* inttoptr (i64 64 to i64*), align 64 diff --git a/test/Transforms/InstCombine/devirt.ll b/test/Transforms/InstCombine/devirt.ll deleted file mode 100644 index 9c7cf5d697e8..000000000000 --- a/test/Transforms/InstCombine/devirt.ll +++ /dev/null @@ -1,39 +0,0 @@ -; RUN: opt -instcombine -S < %s | FileCheck %s - -; CHECK-NOT: getelementptr -; CHECK-NOT: ptrtoint -; CHECK: bitcast i8* -%struct.S = type { i32 (...)** } - -@_ZL1p = internal constant { i64, i64 } { i64 1, i64 0 }, align 8 - -define void @_Z1g1S(%struct.S* %s) nounwind { -entry: - %tmp = load { i64, i64 }* @_ZL1p, align 8 - %memptr.adj = extractvalue { i64, i64 } %tmp, 1 - %0 = bitcast %struct.S* %s to i8* - %1 = getelementptr inbounds i8* %0, i64 %memptr.adj - %this.adjusted = bitcast i8* %1 to %struct.S* - %memptr.ptr = extractvalue { i64, i64 } %tmp, 0 - %2 = and i64 %memptr.ptr, 1 - %memptr.isvirtual = icmp ne i64 %2, 0 - br i1 %memptr.isvirtual, label %memptr.virtual, label %memptr.nonvirtual - -memptr.virtual: ; preds = %entry - %3 = bitcast %struct.S* %this.adjusted to i8** - %memptr.vtable = load i8** %3 - %4 = sub i64 %memptr.ptr, 1 - %5 = getelementptr i8* %memptr.vtable, i64 %4 - %6 = bitcast i8* %5 to void (%struct.S*)** - %memptr.virtualfn = load void (%struct.S*)** %6 - br label %memptr.end - -memptr.nonvirtual: ; preds = %entry - %memptr.nonvirtualfn = inttoptr i64 %memptr.ptr to void (%struct.S*)* - br label %memptr.end - -memptr.end: ; preds = %memptr.nonvirtual, %memptr.virtual - %7 = phi void (%struct.S*)* [ %memptr.virtualfn, %memptr.virtual ], [ %memptr.nonvirtualfn, %memptr.nonvirtual ] - call void %7(%struct.S* %this.adjusted) - ret void -} diff --git a/test/Transforms/InstCombine/div.ll b/test/Transforms/InstCombine/div.ll index 9c7ba9b03059..e0ff07baae7c 100644 --- a/test/Transforms/InstCombine/div.ll +++ b/test/Transforms/InstCombine/div.ll @@ -132,11 +132,11 @@ define i32 @test15(i32 %a, i32 %b) nounwind { } define <2 x i64> @test16(<2 x i64> %x) nounwind { - %shr = lshr <2 x i64> %x, <i64 3, i64 5> - %div = udiv <2 x i64> %shr, <i64 4, i64 6> + %shr = lshr <2 x i64> %x, <i64 5, i64 5> + %div = udiv <2 x i64> %shr, <i64 6, i64 6> ret <2 x i64> %div ; CHECK-LABEL: @test16( -; CHECK-NEXT: udiv <2 x i64> %x, <i64 32, i64 192> +; CHECK-NEXT: udiv <2 x i64> %x, <i64 192, i64 192> ; CHECK-NEXT: ret <2 x i64> } @@ -175,3 +175,153 @@ define i32 @test20(i32 %x) { ; CHECK-NEXT: select i1 %{{.*}}, i32 %x, i32 {{.*}} ; CHECK-NEXT: ret i32 } + +define i32 @test21(i32 %a) { + %shl = shl nsw i32 %a, 2 + %div = sdiv i32 %shl, 12 + ret i32 %div +; CHECK-LABEL: @test21( +; CHECK-NEXT: %div = sdiv i32 %a, 3 +; CHECK-NEXT: ret i32 %div +} + +define i32 @test22(i32 %a) { + %mul = mul nsw i32 %a, 3 + %div = sdiv i32 %mul, 12 + ret i32 %div +; CHECK-LABEL: @test22( +; CHECK-NEXT: %div = sdiv i32 %a, 4 +; CHECK-NEXT: ret i32 %div +} + +define i32 @test23(i32 %a) { + %shl = shl nuw i32 %a, 2 + %div = udiv i32 %shl, 12 + ret i32 %div +; CHECK-LABEL: @test23( +; CHECK-NEXT: %div = udiv i32 %a, 3 +; CHECK-NEXT: ret i32 %div +} + +define i32 @test24(i32 %a) { + %mul = mul nuw i32 %a, 3 + %div = udiv i32 %mul, 12 + ret i32 %div +; CHECK-LABEL: @test24( +; CHECK-NEXT: %div = lshr i32 %a, 2 +; CHECK-NEXT: ret i32 %div +} + +define i32 @test25(i32 %a) { + %shl = shl nsw i32 %a, 2 + %div = sdiv i32 %shl, 2 + ret i32 %div +; CHECK-LABEL: @test25( +; CHECK-NEXT: %div = shl nsw i32 %a, 1 +; CHECK-NEXT: ret i32 %div +} + +define i32 @test26(i32 %a) { + %mul = mul nsw i32 %a, 12 + %div = sdiv i32 %mul, 3 + ret i32 %div +; CHECK-LABEL: @test26( +; CHECK-NEXT: %div = shl nsw i32 %a, 2 +; CHECK-NEXT: ret i32 %div +} + +define i32 @test27(i32 %a) { + %shl = shl nuw i32 %a, 2 + %div = udiv i32 %shl, 2 + ret i32 %div +; CHECK-LABEL: @test27( +; CHECK-NEXT: %div = shl nuw i32 %a, 1 +; CHECK-NEXT: ret i32 %div +} + +define i32 @test28(i32 %a) { + %mul = mul nuw i32 %a, 36 + %div = udiv i32 %mul, 3 + ret i32 %div +; CHECK-LABEL: @test28( +; CHECK-NEXT: %div = mul nuw i32 %a, 12 +; CHECK-NEXT: ret i32 %div +} + +define i32 @test29(i32 %a) { + %mul = shl nsw i32 %a, 31 + %div = sdiv i32 %mul, -2147483648 + ret i32 %div +; CHECK-LABEL: @test29( +; CHECK-NEXT: %[[and:.*]] = and i32 %a, 1 +; CHECK-NEXT: ret i32 %[[and]] +} + +define i32 @test30(i32 %a) { + %mul = shl nuw i32 %a, 31 + %div = udiv i32 %mul, -2147483648 + ret i32 %div +; CHECK-LABEL: @test30( +; CHECK-NEXT: ret i32 %a +} + +define <2 x i32> @test31(<2 x i32> %x) { + %shr = lshr <2 x i32> %x, <i32 31, i32 31> + %div = udiv <2 x i32> %shr, <i32 2147483647, i32 2147483647> + ret <2 x i32> %div +; CHECK-LABEL: @test31( +; CHECK-NEXT: %[[shr:.*]] = lshr <2 x i32> %x, <i32 31, i32 31> +; CHECK-NEXT: udiv <2 x i32> %[[shr]], <i32 2147483647, i32 2147483647> +; CHECK-NEXT: ret <2 x i32> +} + +define i32 @test32(i32 %a, i32 %b) { + %shl = shl i32 2, %b + %div = lshr i32 %shl, 2 + %div2 = udiv i32 %a, %div + ret i32 %div2 +; CHECK-LABEL: @test32( +; CHECK-NEXT: %[[shl:.*]] = shl i32 2, %b +; CHECK-NEXT: %[[shr:.*]] = lshr i32 %[[shl]], 2 +; CHECK-NEXT: %[[div:.*]] = udiv i32 %a, %[[shr]] +; CHECK-NEXT: ret i32 +} + +define <2 x i64> @test33(<2 x i64> %x) nounwind { + %shr = lshr exact <2 x i64> %x, <i64 5, i64 5> + %div = udiv exact <2 x i64> %shr, <i64 6, i64 6> + ret <2 x i64> %div +; CHECK-LABEL: @test33( +; CHECK-NEXT: udiv exact <2 x i64> %x, <i64 192, i64 192> +; CHECK-NEXT: ret <2 x i64> +} + +define <2 x i64> @test34(<2 x i64> %x) nounwind { + %neg = sub nsw <2 x i64> zeroinitializer, %x + %div = sdiv exact <2 x i64> %neg, <i64 3, i64 4> + ret <2 x i64> %div +; CHECK-LABEL: @test34( +; CHECK-NEXT: sdiv exact <2 x i64> %x, <i64 -3, i64 -4> +; CHECK-NEXT: ret <2 x i64> +} + +define i32 @test35(i32 %A) { + %and = and i32 %A, 2147483647 + %mul = sdiv exact i32 %and, 2147483647 + ret i32 %mul +; CHECK-LABEL: @test35( +; CHECK-NEXT: %[[and:.*]] = and i32 %A, 2147483647 +; CHECK-NEXT: %[[udiv:.*]] = udiv exact i32 %[[and]], 2147483647 +; CHECK-NEXT: ret i32 %[[udiv]] +} + +define i32 @test36(i32 %A) { + %and = and i32 %A, 2147483647 + %shl = shl nsw i32 1, %A + %mul = sdiv exact i32 %and, %shl + ret i32 %mul +; CHECK-LABEL: @test36( +; CHECK-NEXT: %[[and:.*]] = and i32 %A, 2147483647 +; CHECK-NEXT: %[[shr:.*]] = lshr exact i32 %[[and]], %A +; CHECK-NEXT: ret i32 %[[shr]] +} diff --git a/test/Transforms/InstCombine/double-float-shrink-1.ll b/test/Transforms/InstCombine/double-float-shrink-1.ll index d958470f1baa..63a02bbd8572 100644 --- a/test/Transforms/InstCombine/double-float-shrink-1.ll +++ b/test/Transforms/InstCombine/double-float-shrink-1.ll @@ -1,349 +1,366 @@ -; RUN: opt < %s -instcombine -enable-double-float-shrink -S | FileCheck %s +; RUN: opt < %s -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" target triple = "x86_64-unknown-linux-gnu" -define float @acos_test(float %f) nounwind readnone { -; CHECK: acos_test +; Check for and against shrinkage when using the +; unsafe-fp-math function attribute on a math lib +; function. This optimization may be overridden by +; the -enable-double-float-shrink option. +; PR17850: http://llvm.org/bugs/show_bug.cgi?id=17850 + +define float @acos_test(float %f) { %conv = fpext float %f to double %call = call double @acos(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: acos_test ; CHECK: call float @acosf(float %f) } -define double @acos_test2(float %f) nounwind readnone { -; CHECK: acos_test2 +define double @acos_test2(float %f) { %conv = fpext float %f to double %call = call double @acos(double %conv) ret double %call +; CHECK-LABEL: acos_test2 ; CHECK: call double @acos(double %conv) } -define float @acosh_test(float %f) nounwind readnone { -; CHECK: acosh_test +define float @acosh_test(float %f) { %conv = fpext float %f to double %call = call double @acosh(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: acosh_test ; CHECK: call float @acoshf(float %f) } -define double @acosh_test2(float %f) nounwind readnone { -; CHECK: acosh_test2 +define double @acosh_test2(float %f) { %conv = fpext float %f to double %call = call double @acosh(double %conv) ret double %call +; CHECK-LABEL: acosh_test2 ; CHECK: call double @acosh(double %conv) } -define float @asin_test(float %f) nounwind readnone { -; CHECK: asin_test +define float @asin_test(float %f) { %conv = fpext float %f to double %call = call double @asin(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: asin_test ; CHECK: call float @asinf(float %f) } -define double @asin_test2(float %f) nounwind readnone { -; CHECK: asin_test2 +define double @asin_test2(float %f) { %conv = fpext float %f to double %call = call double @asin(double %conv) ret double %call +; CHECK-LABEL: asin_test2 ; CHECK: call double @asin(double %conv) } -define float @asinh_test(float %f) nounwind readnone { -; CHECK: asinh_test +define float @asinh_test(float %f) { %conv = fpext float %f to double %call = call double @asinh(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: asinh_test ; CHECK: call float @asinhf(float %f) } -define double @asinh_test2(float %f) nounwind readnone { -; CHECK: asinh_test2 +define double @asinh_test2(float %f) { %conv = fpext float %f to double %call = call double @asinh(double %conv) ret double %call +; CHECK-LABEL: asinh_test2 ; CHECK: call double @asinh(double %conv) } -define float @atan_test(float %f) nounwind readnone { -; CHECK: atan_test +define float @atan_test(float %f) { %conv = fpext float %f to double %call = call double @atan(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: atan_test ; CHECK: call float @atanf(float %f) } -define double @atan_test2(float %f) nounwind readnone { -; CHECK: atan_test2 +define double @atan_test2(float %f) { %conv = fpext float %f to double %call = call double @atan(double %conv) ret double %call +; CHECK-LABEL: atan_test2 ; CHECK: call double @atan(double %conv) } -define float @atanh_test(float %f) nounwind readnone { -; CHECK: atanh_test +define float @atanh_test(float %f) { %conv = fpext float %f to double %call = call double @atanh(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: atanh_test ; CHECK: call float @atanhf(float %f) } -define double @atanh_test2(float %f) nounwind readnone { -; CHECK: atanh_test2 +define double @atanh_test2(float %f) { %conv = fpext float %f to double %call = call double @atanh(double %conv) ret double %call +; CHECK-LABEL: atanh_test2 ; CHECK: call double @atanh(double %conv) } -define float @cbrt_test(float %f) nounwind readnone { -; CHECK: cbrt_test +define float @cbrt_test(float %f) { %conv = fpext float %f to double %call = call double @cbrt(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: cbrt_test ; CHECK: call float @cbrtf(float %f) } -define double @cbrt_test2(float %f) nounwind readnone { -; CHECK: cbrt_test2 +define double @cbrt_test2(float %f) { %conv = fpext float %f to double %call = call double @cbrt(double %conv) ret double %call +; CHECK-LABEL: cbrt_test2 ; CHECK: call double @cbrt(double %conv) } -define float @exp_test(float %f) nounwind readnone { -; CHECK: exp_test +define float @exp_test(float %f) { %conv = fpext float %f to double %call = call double @exp(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: exp_test ; CHECK: call float @expf(float %f) } -define double @exp_test2(float %f) nounwind readnone { -; CHECK: exp_test2 +define double @exp_test2(float %f) { %conv = fpext float %f to double %call = call double @exp(double %conv) ret double %call +; CHECK-LABEL: exp_test2 ; CHECK: call double @exp(double %conv) } -define float @expm1_test(float %f) nounwind readnone { -; CHECK: expm1_test +define float @expm1_test(float %f) { %conv = fpext float %f to double %call = call double @expm1(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: expm1_test ; CHECK: call float @expm1f(float %f) } -define double @expm1_test2(float %f) nounwind readnone { -; CHECK: expm1_test2 +define double @expm1_test2(float %f) { %conv = fpext float %f to double %call = call double @expm1(double %conv) ret double %call +; CHECK-LABEL: expm1_test2 ; CHECK: call double @expm1(double %conv) } -define float @exp10_test(float %f) nounwind readnone { -; CHECK: exp10_test +define float @exp10_test(float %f) { %conv = fpext float %f to double %call = call double @exp10(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 -; FIXME: Re-enable this when Linux allows transforming this again, or when we -; can use builtin attributes to test the transform regardless of OS. -; DISABLED-CHECK: call float @exp10f(float %f) +; CHECK-LABEL: exp10_test ; CHECK: call double @exp10(double %conv) } -define double @exp10_test2(float %f) nounwind readnone { -; CHECK: exp10_test2 +define double @exp10_test2(float %f) { %conv = fpext float %f to double %call = call double @exp10(double %conv) ret double %call +; CHECK-LABEL: exp10_test2 ; CHECK: call double @exp10(double %conv) } -define float @log_test(float %f) nounwind readnone { -; CHECK: log_test +define float @log_test(float %f) { %conv = fpext float %f to double %call = call double @log(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: log_test ; CHECK: call float @logf(float %f) } -define double @log_test2(float %f) nounwind readnone { -; CHECK: log_test2 +define double @log_test2(float %f) { %conv = fpext float %f to double %call = call double @log(double %conv) ret double %call +; CHECK-LABEL: log_test2 ; CHECK: call double @log(double %conv) } -define float @log10_test(float %f) nounwind readnone { -; CHECK: log10_test +define float @log10_test(float %f) { %conv = fpext float %f to double %call = call double @log10(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: log10_test ; CHECK: call float @log10f(float %f) } -define double @log10_test2(float %f) nounwind readnone { -; CHECK: log10_test2 +define double @log10_test2(float %f) { %conv = fpext float %f to double %call = call double @log10(double %conv) ret double %call +; CHECK-LABEL: log10_test2 ; CHECK: call double @log10(double %conv) } -define float @log1p_test(float %f) nounwind readnone { -; CHECK: log1p_test +define float @log1p_test(float %f) { %conv = fpext float %f to double %call = call double @log1p(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: log1p_test ; CHECK: call float @log1pf(float %f) } -define double @log1p_test2(float %f) nounwind readnone { -; CHECK: log1p_test2 +define double @log1p_test2(float %f) { %conv = fpext float %f to double %call = call double @log1p(double %conv) ret double %call +; CHECK-LABEL: log1p_test2 ; CHECK: call double @log1p(double %conv) } -define float @log2_test(float %f) nounwind readnone { -; CHECK: log2_test +define float @log2_test(float %f) { %conv = fpext float %f to double %call = call double @log2(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: log2_test ; CHECK: call float @log2f(float %f) } -define double @log2_test2(float %f) nounwind readnone { -; CHECK: log2_test2 +define double @log2_test2(float %f) { %conv = fpext float %f to double %call = call double @log2(double %conv) ret double %call +; CHECK-LABEL: log2_test2 ; CHECK: call double @log2(double %conv) } -define float @logb_test(float %f) nounwind readnone { -; CHECK: logb_test +define float @logb_test(float %f) { %conv = fpext float %f to double %call = call double @logb(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: logb_test ; CHECK: call float @logbf(float %f) } -define double @logb_test2(float %f) nounwind readnone { -; CHECK: logb_test2 +define double @logb_test2(float %f) { %conv = fpext float %f to double %call = call double @logb(double %conv) ret double %call +; CHECK-LABEL: logb_test2 ; CHECK: call double @logb(double %conv) } -define float @sin_test(float %f) nounwind readnone { -; CHECK: sin_test +define float @sin_test(float %f) { %conv = fpext float %f to double %call = call double @sin(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: sin_test ; CHECK: call float @sinf(float %f) } -define double @sin_test2(float %f) nounwind readnone { -; CHECK: sin_test2 +define double @sin_test2(float %f) { %conv = fpext float %f to double %call = call double @sin(double %conv) ret double %call +; CHECK-LABEL: sin_test2 ; CHECK: call double @sin(double %conv) } -define float @sqrt_test(float %f) nounwind readnone { -; CHECK: sqrt_test +define float @sqrt_test(float %f) { %conv = fpext float %f to double %call = call double @sqrt(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: sqrt_test ; CHECK: call float @sqrtf(float %f) } -define float @sqrt_int_test(float %f) nounwind readnone { -; CHECK: sqrt_int_test +define double @sqrt_test2(float %f) { + %conv = fpext float %f to double + %call = call double @sqrt(double %conv) + ret double %call +; CHECK-LABEL: sqrt_test2 +; CHECK: call double @sqrt(double %conv) +} + +define float @sqrt_int_test(float %f) { %conv = fpext float %f to double %call = call double @llvm.sqrt.f64(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: sqrt_int_test ; CHECK: call float @llvm.sqrt.f32(float %f) } -define double @sqrt_test2(float %f) nounwind readnone { -; CHECK: sqrt_test2 +define double @sqrt_int_test2(float %f) { %conv = fpext float %f to double - %call = call double @sqrt(double %conv) + %call = call double @llvm.sqrt.f64(double %conv) ret double %call -; CHECK: call double @sqrt(double %conv) +; CHECK-LABEL: sqrt_int_test2 +; CHECK: call double @llvm.sqrt.f64(double %conv) } -define float @tan_test(float %f) nounwind readnone { -; CHECK: tan_test + +define float @tan_test(float %f) { %conv = fpext float %f to double %call = call double @tan(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: tan_test ; CHECK: call float @tanf(float %f) } -define double @tan_test2(float %f) nounwind readnone { -; CHECK: tan_test2 +define double @tan_test2(float %f) { %conv = fpext float %f to double %call = call double @tan(double %conv) ret double %call +; CHECK-LABEL: tan_test2 ; CHECK: call double @tan(double %conv) } -define float @tanh_test(float %f) nounwind readnone { -; CHECK: tanh_test +define float @tanh_test(float %f) { %conv = fpext float %f to double %call = call double @tanh(double %conv) %conv1 = fptrunc double %call to float ret float %conv1 +; CHECK-LABEL: tanh_test ; CHECK: call float @tanhf(float %f) } -define double @tanh_test2(float %f) nounwind readnone { -; CHECK: tanh_test2 +define double @tanh_test2(float %f) { %conv = fpext float %f to double %call = call double @tanh(double %conv) ret double %call +; CHECK-LABEL: tanh_test2 ; CHECK: call double @tanh(double %conv) } -declare double @tanh(double) nounwind readnone -declare double @tan(double) nounwind readnone -declare double @sqrt(double) nounwind readnone -declare double @sin(double) nounwind readnone -declare double @log2(double) nounwind readnone -declare double @log1p(double) nounwind readnone -declare double @log10(double) nounwind readnone -declare double @log(double) nounwind readnone -declare double @logb(double) nounwind readnone -declare double @exp10(double) nounwind readnone -declare double @expm1(double) nounwind readnone -declare double @exp(double) nounwind readnone -declare double @cbrt(double) nounwind readnone -declare double @atanh(double) nounwind readnone -declare double @atan(double) nounwind readnone -declare double @acos(double) nounwind readnone -declare double @acosh(double) nounwind readnone -declare double @asin(double) nounwind readnone -declare double @asinh(double) nounwind readnone - -declare double @llvm.sqrt.f64(double) nounwind readnone +declare double @tanh(double) #1 +declare double @tan(double) #1 + +; sqrt is a special case: the shrinking optimization +; is valid even without unsafe-fp-math. +declare double @sqrt(double) +declare double @llvm.sqrt.f64(double) + +declare double @sin(double) #1 +declare double @log2(double) #1 +declare double @log1p(double) #1 +declare double @log10(double) #1 +declare double @log(double) #1 +declare double @logb(double) #1 +declare double @exp10(double) #1 +declare double @expm1(double) #1 +declare double @exp(double) #1 +declare double @cbrt(double) #1 +declare double @atanh(double) #1 +declare double @atan(double) #1 +declare double @acos(double) #1 +declare double @acosh(double) #1 +declare double @asin(double) #1 +declare double @asinh(double) #1 + +attributes #1 = { "unsafe-fp-math"="true" } diff --git a/test/Transforms/InstCombine/fabs.ll b/test/Transforms/InstCombine/fabs.ll new file mode 100644 index 000000000000..0479549bea3f --- /dev/null +++ b/test/Transforms/InstCombine/fabs.ll @@ -0,0 +1,100 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; Make sure all library calls are eliminated when the input is known positive. + +declare float @fabsf(float) +declare double @fabs(double) +declare fp128 @fabsl(fp128) + +define float @square_fabs_call_f32(float %x) { + %mul = fmul float %x, %x + %fabsf = tail call float @fabsf(float %mul) + ret float %fabsf + +; CHECK-LABEL: square_fabs_call_f32( +; CHECK-NEXT: %mul = fmul float %x, %x +; CHECK-NEXT: ret float %mul +} + +define double @square_fabs_call_f64(double %x) { + %mul = fmul double %x, %x + %fabs = tail call double @fabs(double %mul) + ret double %fabs + +; CHECK-LABEL: square_fabs_call_f64( +; CHECK-NEXT: %mul = fmul double %x, %x +; CHECK-NEXT: ret double %mul +} + +define fp128 @square_fabs_call_f128(fp128 %x) { + %mul = fmul fp128 %x, %x + %fabsl = tail call fp128 @fabsl(fp128 %mul) + ret fp128 %fabsl + +; CHECK-LABEL: square_fabs_call_f128( +; CHECK-NEXT: %mul = fmul fp128 %x, %x +; CHECK-NEXT: ret fp128 %mul +} + +; Make sure all intrinsic calls are eliminated when the input is known positive. + +declare float @llvm.fabs.f32(float) +declare double @llvm.fabs.f64(double) +declare fp128 @llvm.fabs.f128(fp128) + +define float @square_fabs_intrinsic_f32(float %x) { + %mul = fmul float %x, %x + %fabsf = tail call float @llvm.fabs.f32(float %mul) + ret float %fabsf + +; CHECK-LABEL: square_fabs_intrinsic_f32( +; CHECK-NEXT: %mul = fmul float %x, %x +; CHECK-NEXT: ret float %mul +} + +define double @square_fabs_intrinsic_f64(double %x) { + %mul = fmul double %x, %x + %fabs = tail call double @llvm.fabs.f64(double %mul) + ret double %fabs + +; CHECK-LABEL: square_fabs_intrinsic_f64( +; CHECK-NEXT: %mul = fmul double %x, %x +; CHECK-NEXT: ret double %mul +} + +define fp128 @square_fabs_intrinsic_f128(fp128 %x) { + %mul = fmul fp128 %x, %x + %fabsl = tail call fp128 @llvm.fabs.f128(fp128 %mul) + ret fp128 %fabsl + +; CHECK-LABEL: square_fabs_intrinsic_f128( +; CHECK-NEXT: %mul = fmul fp128 %x, %x +; CHECK-NEXT: ret fp128 %mul +} + +; Shrinking a library call to a smaller type should not be inhibited by nor inhibit the square optimization. + +define float @square_fabs_shrink_call1(float %x) { + %ext = fpext float %x to double + %sq = fmul double %ext, %ext + %fabs = call double @fabs(double %sq) + %trunc = fptrunc double %fabs to float + ret float %trunc + +; CHECK-LABEL: square_fabs_shrink_call1( +; CHECK-NEXT: %trunc = fmul float %x, %x +; CHECK-NEXT: ret float %trunc +} + +define float @square_fabs_shrink_call2(float %x) { + %sq = fmul float %x, %x + %ext = fpext float %sq to double + %fabs = call double @fabs(double %ext) + %trunc = fptrunc double %fabs to float + ret float %trunc + +; CHECK-LABEL: square_fabs_shrink_call2( +; CHECK-NEXT: %sq = fmul float %x, %x +; CHECK-NEXT: ret float %sq +} + diff --git a/test/Transforms/InstCombine/fast-math.ll b/test/Transforms/InstCombine/fast-math.ll index 2ee4b0f2c381..c6081c399253 100644 --- a/test/Transforms/InstCombine/fast-math.ll +++ b/test/Transforms/InstCombine/fast-math.ll @@ -93,7 +93,7 @@ define float @fold9(float %f1, float %f2) { ret float %t3 ; CHECK-LABEL: @fold9( -; CHECK: fsub fast float 0.000000e+00, %f2 +; CHECK: fsub fast float -0.000000e+00, %f2 } ; Let C3 = C1 + C2. (f1 + C1) + (f2 + C2) => (f1 + f2) + C3 instead of @@ -322,6 +322,14 @@ define float @fneg1(float %f1, float %f2) { ; CHECK: fmul float %f1, %f2 } +define float @fneg2(float %x) { + %sub = fsub nsz float 0.0, %x + ret float %sub +; CHECK-LABEL: @fneg2( +; CHECK-NEXT: fsub nsz float -0.000000e+00, %x +; CHECK-NEXT: ret float +} + ; ========================================================================= ; ; Testing-cases about div @@ -530,3 +538,173 @@ define float @fact_div6(float %x) { ; CHECK: fact_div6 ; CHECK: %t3 = fsub fast float %t1, %t2 } + +; ========================================================================= +; +; Test-cases for square root +; +; ========================================================================= + +; A squared factor fed into a square root intrinsic should be hoisted out +; as a fabs() value. +; We have to rely on a function-level attribute to enable this optimization +; because intrinsics don't currently have access to IR-level fast-math +; flags. If that changes, we can relax the requirement on all of these +; tests to just specify 'fast' on the sqrt. + +attributes #0 = { "unsafe-fp-math" = "true" } + +declare double @llvm.sqrt.f64(double) + +define double @sqrt_intrinsic_arg_squared(double %x) #0 { + %mul = fmul fast double %x, %x + %sqrt = call double @llvm.sqrt.f64(double %mul) + ret double %sqrt + +; CHECK-LABEL: sqrt_intrinsic_arg_squared( +; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) +; CHECK-NEXT: ret double %fabs +} + +; Check all 6 combinations of a 3-way multiplication tree where +; one factor is repeated. + +define double @sqrt_intrinsic_three_args1(double %x, double %y) #0 { + %mul = fmul fast double %y, %x + %mul2 = fmul fast double %mul, %x + %sqrt = call double @llvm.sqrt.f64(double %mul2) + ret double %sqrt + +; CHECK-LABEL: sqrt_intrinsic_three_args1( +; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y) +; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1 +; CHECK-NEXT: ret double %1 +} + +define double @sqrt_intrinsic_three_args2(double %x, double %y) #0 { + %mul = fmul fast double %x, %y + %mul2 = fmul fast double %mul, %x + %sqrt = call double @llvm.sqrt.f64(double %mul2) + ret double %sqrt + +; CHECK-LABEL: sqrt_intrinsic_three_args2( +; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y) +; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1 +; CHECK-NEXT: ret double %1 +} + +define double @sqrt_intrinsic_three_args3(double %x, double %y) #0 { + %mul = fmul fast double %x, %x + %mul2 = fmul fast double %mul, %y + %sqrt = call double @llvm.sqrt.f64(double %mul2) + ret double %sqrt + +; CHECK-LABEL: sqrt_intrinsic_three_args3( +; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y) +; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1 +; CHECK-NEXT: ret double %1 +} + +define double @sqrt_intrinsic_three_args4(double %x, double %y) #0 { + %mul = fmul fast double %y, %x + %mul2 = fmul fast double %x, %mul + %sqrt = call double @llvm.sqrt.f64(double %mul2) + ret double %sqrt + +; CHECK-LABEL: sqrt_intrinsic_three_args4( +; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y) +; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1 +; CHECK-NEXT: ret double %1 +} + +define double @sqrt_intrinsic_three_args5(double %x, double %y) #0 { + %mul = fmul fast double %x, %y + %mul2 = fmul fast double %x, %mul + %sqrt = call double @llvm.sqrt.f64(double %mul2) + ret double %sqrt + +; CHECK-LABEL: sqrt_intrinsic_three_args5( +; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y) +; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1 +; CHECK-NEXT: ret double %1 +} + +define double @sqrt_intrinsic_three_args6(double %x, double %y) #0 { + %mul = fmul fast double %x, %x + %mul2 = fmul fast double %y, %mul + %sqrt = call double @llvm.sqrt.f64(double %mul2) + ret double %sqrt + +; CHECK-LABEL: sqrt_intrinsic_three_args6( +; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y) +; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1 +; CHECK-NEXT: ret double %1 +} + +define double @sqrt_intrinsic_arg_4th(double %x) #0 { + %mul = fmul fast double %x, %x + %mul2 = fmul fast double %mul, %mul + %sqrt = call double @llvm.sqrt.f64(double %mul2) + ret double %sqrt + +; CHECK-LABEL: sqrt_intrinsic_arg_4th( +; CHECK-NEXT: %mul = fmul fast double %x, %x +; CHECK-NEXT: ret double %mul +} + +define double @sqrt_intrinsic_arg_5th(double %x) #0 { + %mul = fmul fast double %x, %x + %mul2 = fmul fast double %mul, %x + %mul3 = fmul fast double %mul2, %mul + %sqrt = call double @llvm.sqrt.f64(double %mul3) + ret double %sqrt + +; CHECK-LABEL: sqrt_intrinsic_arg_5th( +; CHECK-NEXT: %mul = fmul fast double %x, %x +; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %x) +; CHECK-NEXT: %1 = fmul fast double %mul, %sqrt1 +; CHECK-NEXT: ret double %1 +} + +; Check that square root calls have the same behavior. + +declare float @sqrtf(float) +declare double @sqrt(double) +declare fp128 @sqrtl(fp128) + +define float @sqrt_call_squared_f32(float %x) #0 { + %mul = fmul fast float %x, %x + %sqrt = call float @sqrtf(float %mul) + ret float %sqrt + +; CHECK-LABEL: sqrt_call_squared_f32( +; CHECK-NEXT: %fabs = call float @llvm.fabs.f32(float %x) +; CHECK-NEXT: ret float %fabs +} + +define double @sqrt_call_squared_f64(double %x) #0 { + %mul = fmul fast double %x, %x + %sqrt = call double @sqrt(double %mul) + ret double %sqrt + +; CHECK-LABEL: sqrt_call_squared_f64( +; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) +; CHECK-NEXT: ret double %fabs +} + +define fp128 @sqrt_call_squared_f128(fp128 %x) #0 { + %mul = fmul fast fp128 %x, %x + %sqrt = call fp128 @sqrtl(fp128 %mul) + ret fp128 %sqrt + +; CHECK-LABEL: sqrt_call_squared_f128( +; CHECK-NEXT: %fabs = call fp128 @llvm.fabs.f128(fp128 %x) +; CHECK-NEXT: ret fp128 %fabs +} + diff --git a/test/Transforms/InstCombine/fcmp.ll b/test/Transforms/InstCombine/fcmp.ll index afc6782a0122..ee39d1084ebc 100644 --- a/test/Transforms/InstCombine/fcmp.ll +++ b/test/Transforms/InstCombine/fcmp.ll @@ -1,5 +1,7 @@ ; RUN: opt -S -instcombine < %s | FileCheck %s +declare double @llvm.fabs.f64(double) nounwind readnone + define i1 @test1(float %x, float %y) nounwind { %ext1 = fpext float %x to double %ext2 = fpext float %y to double @@ -81,6 +83,16 @@ define i32 @test9(double %a) nounwind { ; CHECK: ret i32 0 } +define i32 @test9_intrinsic(double %a) nounwind { + %call = tail call double @llvm.fabs.f64(double %a) nounwind + %cmp = fcmp olt double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: @test9_intrinsic( +; CHECK-NOT: fabs +; CHECK: ret i32 0 +} + define i32 @test10(double %a) nounwind { %call = tail call double @fabs(double %a) nounwind %cmp = fcmp ole double %call, 0.000000e+00 @@ -91,6 +103,16 @@ define i32 @test10(double %a) nounwind { ; CHECK: fcmp oeq double %a, 0.000000e+00 } +define i32 @test10_intrinsic(double %a) nounwind { + %call = tail call double @llvm.fabs.f64(double %a) nounwind + %cmp = fcmp ole double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: @test10_intrinsic( +; CHECK-NOT: fabs +; CHECK: fcmp oeq double %a, 0.000000e+00 +} + define i32 @test11(double %a) nounwind { %call = tail call double @fabs(double %a) nounwind %cmp = fcmp ogt double %call, 0.000000e+00 @@ -101,6 +123,16 @@ define i32 @test11(double %a) nounwind { ; CHECK: fcmp one double %a, 0.000000e+00 } +define i32 @test11_intrinsic(double %a) nounwind { + %call = tail call double @llvm.fabs.f64(double %a) nounwind + %cmp = fcmp ogt double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: @test11_intrinsic( +; CHECK-NOT: fabs +; CHECK: fcmp one double %a, 0.000000e+00 +} + define i32 @test12(double %a) nounwind { %call = tail call double @fabs(double %a) nounwind %cmp = fcmp oge double %call, 0.000000e+00 @@ -111,6 +143,16 @@ define i32 @test12(double %a) nounwind { ; CHECK: fcmp ord double %a, 0.000000e+00 } +define i32 @test12_intrinsic(double %a) nounwind { + %call = tail call double @llvm.fabs.f64(double %a) nounwind + %cmp = fcmp oge double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: @test12_intrinsic( +; CHECK-NOT: fabs +; CHECK: fcmp ord double %a, 0.000000e+00 +} + define i32 @test13(double %a) nounwind { %call = tail call double @fabs(double %a) nounwind %cmp = fcmp une double %call, 0.000000e+00 @@ -121,6 +163,16 @@ define i32 @test13(double %a) nounwind { ; CHECK: fcmp une double %a, 0.000000e+00 } +define i32 @test13_intrinsic(double %a) nounwind { + %call = tail call double @llvm.fabs.f64(double %a) nounwind + %cmp = fcmp une double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: @test13_intrinsic( +; CHECK-NOT: fabs +; CHECK: fcmp une double %a, 0.000000e+00 +} + define i32 @test14(double %a) nounwind { %call = tail call double @fabs(double %a) nounwind %cmp = fcmp oeq double %call, 0.000000e+00 @@ -131,6 +183,16 @@ define i32 @test14(double %a) nounwind { ; CHECK: fcmp oeq double %a, 0.000000e+00 } +define i32 @test14_intrinsic(double %a) nounwind { + %call = tail call double @llvm.fabs.f64(double %a) nounwind + %cmp = fcmp oeq double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: @test14_intrinsic( +; CHECK-NOT: fabs +; CHECK: fcmp oeq double %a, 0.000000e+00 +} + define i32 @test15(double %a) nounwind { %call = tail call double @fabs(double %a) nounwind %cmp = fcmp one double %call, 0.000000e+00 @@ -141,6 +203,16 @@ define i32 @test15(double %a) nounwind { ; CHECK: fcmp one double %a, 0.000000e+00 } +define i32 @test15_intrinsic(double %a) nounwind { + %call = tail call double @llvm.fabs.f64(double %a) nounwind + %cmp = fcmp one double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: @test15_intrinsic( +; CHECK-NOT: fabs +; CHECK: fcmp one double %a, 0.000000e+00 +} + define i32 @test16(double %a) nounwind { %call = tail call double @fabs(double %a) nounwind %cmp = fcmp ueq double %call, 0.000000e+00 @@ -151,6 +223,16 @@ define i32 @test16(double %a) nounwind { ; CHECK: fcmp ueq double %a, 0.000000e+00 } +define i32 @test16_intrinsic(double %a) nounwind { + %call = tail call double @llvm.fabs.f64(double %a) nounwind + %cmp = fcmp ueq double %call, 0.000000e+00 + %conv = zext i1 %cmp to i32 + ret i32 %conv +; CHECK-LABEL: @test16_intrinsic( +; CHECK-NOT: fabs +; CHECK: fcmp ueq double %a, 0.000000e+00 +} + ; Don't crash. define i32 @test17(double %a, double (double)* %p) nounwind { %call = tail call double %p(double %a) nounwind diff --git a/test/Transforms/InstCombine/float-shrink-compare.ll b/test/Transforms/InstCombine/float-shrink-compare.ll index e50046790da8..a08f9531d217 100644 --- a/test/Transforms/InstCombine/float-shrink-compare.ll +++ b/test/Transforms/InstCombine/float-shrink-compare.ll @@ -222,8 +222,46 @@ define i32 @test18(float %x, float %y, float %z) nounwind uwtable { ; CHECK-NEXT: fcmp oeq float %fmaxf, %z } +define i32 @test19(float %x, float %y, float %z) nounwind uwtable { + %1 = fpext float %x to double + %2 = fpext float %y to double + %3 = call double @copysign(double %1, double %2) nounwind + %4 = fpext float %z to double + %5 = fcmp oeq double %3, %4 + %6 = zext i1 %5 to i32 + ret i32 %6 +; CHECK-LABEL: @test19( +; CHECK-NEXT: %copysignf = call float @copysignf(float %x, float %y) +; CHECK-NEXT: fcmp oeq float %copysignf, %z +} + +define i32 @test20(float %x, float %y) nounwind uwtable { + %1 = fpext float %y to double + %2 = fpext float %x to double + %3 = call double @fmin(double 1.000000e+00, double %2) nounwind + %4 = fcmp oeq double %1, %3 + %5 = zext i1 %4 to i32 + ret i32 %5 +; CHECK-LABEL: @test20( +; CHECK-NEXT: %fminf = call float @fminf(float 1.000000e+00, float %x) +; CHECK-NEXT: fcmp oeq float %fminf, %y +} + +define i32 @test21(float %x, float %y) nounwind uwtable { + %1 = fpext float %y to double + %2 = fpext float %x to double + %3 = call double @fmin(double 1.300000e+00, double %2) nounwind + %4 = fcmp oeq double %1, %3 + %5 = zext i1 %4 to i32 + ret i32 %5 +; should not be changed to fminf as the constant would loose precision +; CHECK-LABEL: @test21( +; CHECK: %3 = call double @fmin(double 1.300000e+00, double %2) +} + declare double @fabs(double) nounwind readnone declare double @ceil(double) nounwind readnone +declare double @copysign(double, double) nounwind readnone declare double @floor(double) nounwind readnone declare double @nearbyint(double) nounwind readnone declare double @rint(double) nounwind readnone diff --git a/test/Transforms/InstCombine/fmul.ll b/test/Transforms/InstCombine/fmul.ll index 18cbf9da5361..a776765ac2ca 100644 --- a/test/Transforms/InstCombine/fmul.ll +++ b/test/Transforms/InstCombine/fmul.ll @@ -123,3 +123,32 @@ define float @test11(float %x, float %y) { ; CHECK-NOT: fadd float ; CHECK: fadd fast float } + +; PR21126: http://llvm.org/bugs/show_bug.cgi?id=21126 +; With unsafe/fast math, sqrt(X) * sqrt(X) is just X. +declare double @llvm.sqrt.f64(double) + +define double @sqrt_squared1(double %f) { + %sqrt = call double @llvm.sqrt.f64(double %f) + %mul = fmul fast double %sqrt, %sqrt + ret double %mul +; CHECK-LABEL: @sqrt_squared1( +; CHECK-NEXT: ret double %f +} + +; With unsafe/fast math, sqrt(X) * sqrt(X) is just X, +; but make sure another use of the sqrt is intact. +; Note that the remaining fmul is altered but is not 'fast' +; itself because it was not marked 'fast' originally. +; Thus, we have an overall fast result, but no more indication of +; 'fast'ness in the code. +define double @sqrt_squared2(double %f) { + %sqrt = call double @llvm.sqrt.f64(double %f) + %mul1 = fmul fast double %sqrt, %sqrt + %mul2 = fmul double %mul1, %sqrt + ret double %mul2 +; CHECK-LABEL: @sqrt_squared2( +; CHECK-NEXT: %sqrt = call double @llvm.sqrt.f64(double %f) +; CHECK-NEXT: %mul2 = fmul double %sqrt, %f +; CHECK-NEXT: ret double %mul2 +} diff --git a/test/Transforms/InstCombine/fold-phi.ll b/test/Transforms/InstCombine/fold-phi.ll index bd01d58aa586..c6bb1b36335b 100644 --- a/test/Transforms/InstCombine/fold-phi.ll +++ b/test/Transforms/InstCombine/fold-phi.ll @@ -17,23 +17,23 @@ end: ret float %add5 } -; CHECK: fold_phi -define float @fold_phi(float %a) nounwind { +; CHECK-LABEL: @pr21377( +define void @pr21377(i32) { entry: - br label %for.body - -for.body: -; CHECK: phi float -; CHECK-NEXT: br i1 undef - %sum.057 = phi float [ 0.000000e+00, %entry ], [ %add5, %bb0 ] - %add5 = fadd float %sum.057, 1.0 ;; Should be moved to the latch! - br i1 undef, label %bb0, label %end - -; CHECK: bb0: -bb0: -; CHECK: fadd float - br label %for.body - -end: - ret float %add5 + br label %while.body + +while.body: ; preds = %if.end, %entry + %phi1 = phi i64 [ undef, %entry ], [ %or2, %if.end ] + %zext = zext i32 %0 to i64 + br i1 undef, label %if.end, label %if.else + +if.else: ; preds = %while.body + %or1 = or i64 %phi1, %zext + %and = and i64 %or1, 4294967295 + br label %if.end + +if.end: ; preds = %if.else, %while.body + %phi2 = phi i64 [ %and, %if.else ], [ undef, %while.body ] + %or2 = or i64 %phi2, %zext + br label %while.body } diff --git a/test/Transforms/InstCombine/fpcast.ll b/test/Transforms/InstCombine/fpcast.ll index 9be66fd42c68..8319624b87c9 100644 --- a/test/Transforms/InstCombine/fpcast.ll +++ b/test/Transforms/InstCombine/fpcast.ll @@ -53,3 +53,35 @@ define half @test5(float %a, float %b, float %c) { } declare float @llvm.fabs.f32(float) nounwind readonly + +define <1 x float> @test6(<1 x double> %V) { + %frem = frem <1 x double> %V, %V + %trunc = fptrunc <1 x double> %frem to <1 x float> + ret <1 x float> %trunc +; CHECK-LABEL: @test6 +; CHECK-NEXT: %[[frem:.*]] = frem <1 x double> %V, %V +; CHECK-NEXT: %[[trunc:.*]] = fptrunc <1 x double> %[[frem]] to <1 x float> +; CHECK-NEXT: ret <1 x float> %trunc +} + +define float @test7(double %V) { + %frem = frem double %V, 1.000000e+00 + %trunc = fptrunc double %frem to float + ret float %trunc +; CHECK-LABEL: @test7 +; CHECK-NEXT: %[[frem:.*]] = frem double %V, 1.000000e+00 +; CHECK-NEXT: %[[trunc:.*]] = fptrunc double %frem to float +; CHECK-NEXT: ret float %trunc +} + +define float @test8(float %V) { + %fext = fpext float %V to double + %frem = frem double %fext, 1.000000e-01 + %trunc = fptrunc double %frem to float + ret float %trunc +; CHECK-LABEL: @test8 +; CHECK-NEXT: %[[fext:.*]] = fpext float %V to double +; CHECK-NEXT: %[[frem:.*]] = frem double %fext, 1.000000e-01 +; CHECK-NEXT: %[[trunc:.*]] = fptrunc double %frem to float +; CHECK-NEXT: ret float %trunc +} diff --git a/test/Transforms/InstCombine/getelementptr.ll b/test/Transforms/InstCombine/getelementptr.ll index 3240c6d2a4d0..94cc1803073a 100644 --- a/test/Transforms/InstCombine/getelementptr.ll +++ b/test/Transforms/InstCombine/getelementptr.ll @@ -6,6 +6,7 @@ target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64" %pair = type { i32, i32 } %struct.B = type { double } %struct.A = type { %struct.B, i32, i32 } +%struct.C = type { [7 x i8] } @Global = constant [10 x i8] c"helloworld" @@ -580,6 +581,16 @@ define i32 addrspace(1)* @test33_array_struct_as1([10 x %struct.Key] addrspace(1 ret i32 addrspace(1)* %C } +define i32 addrspace(1)* @test33_addrspacecast(%struct.Key* %A) { +; CHECK-LABEL: @test33_addrspacecast( +; CHECK: %C = getelementptr %struct.Key* %A, i64 0, i32 0, i32 1 +; CHECK-NEXT: addrspacecast i32* %C to i32 addrspace(1)* +; CHECK-NEXT: ret + %B = addrspacecast %struct.Key* %A to %struct.anon addrspace(1)* + %C = getelementptr %struct.anon addrspace(1)* %B, i32 0, i32 2 + ret i32 addrspace(1)* %C +} + %T2 = type { i8*, i8 } define i8* @test34(i8* %Val, i64 %V) nounwind { entry: @@ -591,8 +602,8 @@ entry: %C = load i8** %B, align 8 ret i8* %C ; CHECK-LABEL: @test34( -; CHECK: %V.c = inttoptr i64 %V to i8* -; CHECK: ret i8* %V.c +; CHECK: %[[C:.*]] = inttoptr i64 %V to i8* +; CHECK: ret i8* %[[C]] } %t0 = type { i8*, [19 x i8] } @@ -692,7 +703,7 @@ define void @test39(%struct.ham* %arg, i8 %arg1) nounwind { ; CHECK-LABEL: @test39( ; CHECK: getelementptr inbounds %struct.ham* %arg, i64 0, i32 2 -; CHECK: getelementptr inbounds i8* %tmp3, i64 -8 +; CHECK: getelementptr inbounds i8* %{{.+}}, i64 -8 } define i1 @pr16483([1 x i8]* %a, [1 x i8]* %b) { @@ -803,6 +814,78 @@ define i16 @test41([3 x i32] addrspace(1)* %array) { ; CHECK-NEXT: ret i16 8 } +define i8* @test42(i8* %c1, i8* %c2) { + %ptrtoint = ptrtoint i8* %c1 to i64 + %sub = sub i64 0, %ptrtoint + %gep = getelementptr inbounds i8* %c2, i64 %sub + ret i8* %gep + +; CHECK-LABEL: @test42( +; CHECK-NEXT: [[PTRTOINT1:%.*]] = ptrtoint i8* %c1 to i64 +; CHECK-NEXT: [[PTRTOINT2:%.*]] = ptrtoint i8* %c2 to i64 +; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[PTRTOINT2]], [[PTRTOINT1]] +; CHECK-NEXT: [[INTTOPTR:%.*]] = inttoptr i64 [[SUB]] to i8* +; CHECK-NEXT: ret i8* [[INTTOPTR]] +} + +define i16* @test43(i16* %c1, i16* %c2) { + %ptrtoint = ptrtoint i16* %c1 to i64 + %sub = sub i64 0, %ptrtoint + %shr = ashr i64 %sub, 1 + %gep = getelementptr inbounds i16* %c2, i64 %shr + ret i16* %gep + +; CHECK-LABEL: @test43( +; CHECK-NEXT: [[PTRTOINT1:%.*]] = ptrtoint i16* %c1 to i64 +; CHECK-NEXT: [[PTRTOINT2:%.*]] = ptrtoint i16* %c2 to i64 +; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[PTRTOINT2]], [[PTRTOINT1]] +; CHECK-NEXT: [[INTTOPTR:%.*]] = inttoptr i64 [[SUB]] to i16* +; CHECK-NEXT: ret i16* [[INTTOPTR]] +} + +define %struct.C* @test44(%struct.C* %c1, %struct.C* %c2) { + %ptrtoint = ptrtoint %struct.C* %c1 to i64 + %sub = sub i64 0, %ptrtoint + %shr = sdiv i64 %sub, 7 + %gep = getelementptr inbounds %struct.C* %c2, i64 %shr + ret %struct.C* %gep + +; CHECK-LABEL: @test44( +; CHECK-NEXT: [[PTRTOINT1:%.*]] = ptrtoint %struct.C* %c1 to i64 +; CHECK-NEXT: [[PTRTOINT2:%.*]] = ptrtoint %struct.C* %c2 to i64 +; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[PTRTOINT2]], [[PTRTOINT1]] +; CHECK-NEXT: [[INTTOPTR:%.*]] = inttoptr i64 [[SUB]] to %struct.C* +; CHECK-NEXT: ret %struct.C* [[INTTOPTR]] +} + +define %struct.C* @test45(%struct.C* %c1, %struct.C** %c2) { + %ptrtoint1 = ptrtoint %struct.C* %c1 to i64 + %ptrtoint2 = ptrtoint %struct.C** %c2 to i64 + %sub = sub i64 %ptrtoint2, %ptrtoint1 ; C2 - C1 + %shr = sdiv i64 %sub, 7 + %gep = getelementptr inbounds %struct.C* %c1, i64 %shr ; C1 + (C2 - C1) + ret %struct.C* %gep + +; CHECK-LABEL: @test45( +; CHECK-NEXT: [[BITCAST:%.*]] = bitcast %struct.C** %c2 to %struct.C* +; CHECK-NEXT: ret %struct.C* [[BITCAST]] +} + +define %struct.C* @test46(%struct.C* %c1, %struct.C* %c2, i64 %N) { + %ptrtoint = ptrtoint %struct.C* %c1 to i64 + %sub = sub i64 0, %ptrtoint + %sdiv = sdiv i64 %sub, %N + %gep = getelementptr inbounds %struct.C* %c2, i64 %sdiv + ret %struct.C* %gep + +; CHECK-LABEL: @test46( +; CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint %struct.C* %c1 to i64 +; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[PTRTOINT]] +; CHECK-NEXT: [[SDIV:%.*]] = sdiv i64 [[SUB]], %N +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds %struct.C* %c2, i64 %sdiv +; CHECK-NEXT: ret %struct.C* [[GEP]] +} + define i32 addrspace(1)* @ascast_0_gep(i32* %p) nounwind { ; CHECK-LABEL: @ascast_0_gep( ; CHECK-NOT: getelementptr diff --git a/test/Transforms/InstCombine/icmp-logical.ll b/test/Transforms/InstCombine/icmp-logical.ll index d5d8cbc8c26e..faae2016e207 100644 --- a/test/Transforms/InstCombine/icmp-logical.ll +++ b/test/Transforms/InstCombine/icmp-logical.ll @@ -150,3 +150,23 @@ define i1 @nomask_rhs(i32 %in) { %val = or i1 %tst1, %tst2 ret i1 %val } + +define i1 @fold_mask_cmps_to_false(i32 %x) { +; CHECK-LABEL: @fold_mask_cmps_to_false +; CHECK: ret i1 false + %1 = and i32 %x, 2147483647 + %2 = icmp eq i32 %1, 0 + %3 = icmp eq i32 %x, 2147483647 + %4 = and i1 %3, %2 + ret i1 %4 +} + +define i1 @fold_mask_cmps_to_true(i32 %x) { +; CHECK-LABEL: @fold_mask_cmps_to_true +; CHECK: ret i1 true + %1 = and i32 %x, 2147483647 + %2 = icmp ne i32 %1, 0 + %3 = icmp ne i32 %x, 2147483647 + %4 = or i1 %3, %2 + ret i1 %4 +} diff --git a/test/Transforms/InstCombine/icmp-range.ll b/test/Transforms/InstCombine/icmp-range.ll new file mode 100644 index 000000000000..0911ab03c601 --- /dev/null +++ b/test/Transforms/InstCombine/icmp-range.ll @@ -0,0 +1,61 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +; These should be InstSimplify checks, but most of the code +; is currently only in InstCombine. TODO: move supporting code + +; Definitely out of range +define i1 @test_nonzero(i32* nocapture readonly %arg) { +; CHECK-LABEL:test_nonzero +; CHECK: ret i1 true + %val = load i32* %arg, !range !0 + %rval = icmp ne i32 %val, 0 + ret i1 %rval +} +define i1 @test_nonzero2(i32* nocapture readonly %arg) { +; CHECK-LABEL:test_nonzero2 +; CHECK: ret i1 false + %val = load i32* %arg, !range !0 + %rval = icmp eq i32 %val, 0 + ret i1 %rval +} + +; Potentially in range +define i1 @test_nonzero3(i32* nocapture readonly %arg) { +; CHECK-LABEL: test_nonzero3 +; Check that this does not trigger - it wouldn't be legal +; CHECK: icmp + %val = load i32* %arg, !range !1 + %rval = icmp ne i32 %val, 0 + ret i1 %rval +} + +; Definitely in range +define i1 @test_nonzero4(i8* nocapture readonly %arg) { +; CHECK-LABEL: test_nonzero4 +; CHECK: ret i1 false + %val = load i8* %arg, !range !2 + %rval = icmp ne i8 %val, 0 + ret i1 %rval +} + +define i1 @test_nonzero5(i8* nocapture readonly %arg) { +; CHECK-LABEL: test_nonzero5 +; CHECK: ret i1 false + %val = load i8* %arg, !range !2 + %rval = icmp ugt i8 %val, 0 + ret i1 %rval +} + +; Cheaper checks (most values in range meet requirements) +define i1 @test_nonzero6(i8* %argw) { +; CHECK-LABEL: test_nonzero6 +; CHECK: icmp ne i8 %val, 0 + %val = load i8* %argw, !range !3 + %rval = icmp sgt i8 %val, 0 + ret i1 %rval +} + + +!0 = !{i32 1, i32 6} +!1 = !{i32 0, i32 6} +!2 = !{i8 0, i8 1} +!3 = !{i8 0, i8 6} diff --git a/test/Transforms/InstCombine/icmp-shr.ll b/test/Transforms/InstCombine/icmp-shr.ll new file mode 100644 index 000000000000..52414b99cca7 --- /dev/null +++ b/test/Transforms/InstCombine/icmp-shr.ll @@ -0,0 +1,378 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-p1:16:16:16-p2:32:32:32-p3: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" + +; CHECK-LABEL: @lshr_eq_msb_low_last_zero +; CHECK-NEXT: icmp ugt i8 %a, 6 +define i1 @lshr_eq_msb_low_last_zero(i8 %a) { + %shr = lshr i8 127, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @ashr_eq_msb_low_second_zero +; CHECK-NEXT: icmp ugt i8 %a, 6 +define i1 @ashr_eq_msb_low_second_zero(i8 %a) { + %shr = ashr i8 127, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @lshr_ne_msb_low_last_zero +; CHECK-NEXT: icmp ult i8 %a, 7 +define i1 @lshr_ne_msb_low_last_zero(i8 %a) { + %shr = lshr i8 127, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @ashr_ne_msb_low_second_zero +; CHECK-NEXT: icmp ult i8 %a, 7 +define i1 @ashr_ne_msb_low_second_zero(i8 %a) { + %shr = ashr i8 127, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @ashr_eq_both_equal +; CHECK-NEXT: icmp eq i8 %a, 0 +define i1 @ashr_eq_both_equal(i8 %a) { + %shr = ashr i8 128, %a + %cmp = icmp eq i8 %shr, 128 + ret i1 %cmp +} + +; CHECK-LABEL: @ashr_ne_both_equal +; CHECK-NEXT: icmp ne i8 %a, 0 +define i1 @ashr_ne_both_equal(i8 %a) { + %shr = ashr i8 128, %a + %cmp = icmp ne i8 %shr, 128 + ret i1 %cmp +} + +; CHECK-LABEL: @lshr_eq_both_equal +; CHECK-NEXT: icmp eq i8 %a, 0 +define i1 @lshr_eq_both_equal(i8 %a) { + %shr = lshr i8 127, %a + %cmp = icmp eq i8 %shr, 127 + ret i1 %cmp +} + +; CHECK-LABEL: @lshr_ne_both_equal +; CHECK-NEXT: icmp ne i8 %a, 0 +define i1 @lshr_ne_both_equal(i8 %a) { + %shr = lshr i8 127, %a + %cmp = icmp ne i8 %shr, 127 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_eq_both_equal +; CHECK-NEXT: icmp eq i8 %a, 0 +define i1 @exact_ashr_eq_both_equal(i8 %a) { + %shr = ashr exact i8 128, %a + %cmp = icmp eq i8 %shr, 128 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_ne_both_equal +; CHECK-NEXT: icmp ne i8 %a, 0 +define i1 @exact_ashr_ne_both_equal(i8 %a) { + %shr = ashr exact i8 128, %a + %cmp = icmp ne i8 %shr, 128 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_eq_both_equal +; CHECK-NEXT: icmp eq i8 %a, 0 +define i1 @exact_lshr_eq_both_equal(i8 %a) { + %shr = lshr exact i8 126, %a + %cmp = icmp eq i8 %shr, 126 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_ne_both_equal +; CHECK-NEXT: icmp ne i8 %a, 0 +define i1 @exact_lshr_ne_both_equal(i8 %a) { + %shr = lshr exact i8 126, %a + %cmp = icmp ne i8 %shr, 126 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_eq_opposite_msb +; CHECK-NEXT: icmp eq i8 %a, 7 +define i1 @exact_lshr_eq_opposite_msb(i8 %a) { + %shr = lshr exact i8 -128, %a + %cmp = icmp eq i8 %shr, 1 + ret i1 %cmp +} + +; CHECK-LABEL: @lshr_eq_opposite_msb +; CHECK-NEXT: icmp eq i8 %a, 7 +define i1 @lshr_eq_opposite_msb(i8 %a) { + %shr = lshr i8 -128, %a + %cmp = icmp eq i8 %shr, 1 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_ne_opposite_msb +; CHECK-NEXT: icmp ne i8 %a, 7 +define i1 @exact_lshr_ne_opposite_msb(i8 %a) { + %shr = lshr exact i8 -128, %a + %cmp = icmp ne i8 %shr, 1 + ret i1 %cmp +} + +; CHECK-LABEL: @lshr_ne_opposite_msb +; CHECK-NEXT: icmp ne i8 %a, 7 +define i1 @lshr_ne_opposite_msb(i8 %a) { + %shr = lshr i8 -128, %a + %cmp = icmp ne i8 %shr, 1 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_eq +; CHECK-NEXT: icmp eq i8 %a, 7 +define i1 @exact_ashr_eq(i8 %a) { + %shr = ashr exact i8 -128, %a + %cmp = icmp eq i8 %shr, -1 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_ne +; CHECK-NEXT: icmp ne i8 %a, 7 +define i1 @exact_ashr_ne(i8 %a) { + %shr = ashr exact i8 -128, %a + %cmp = icmp ne i8 %shr, -1 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_eq +; CHECK-NEXT: icmp eq i8 %a, 2 +define i1 @exact_lshr_eq(i8 %a) { + %shr = lshr exact i8 4, %a + %cmp = icmp eq i8 %shr, 1 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_ne +; CHECK-NEXT: icmp ne i8 %a, 2 +define i1 @exact_lshr_ne(i8 %a) { + %shr = lshr exact i8 4, %a + %cmp = icmp ne i8 %shr, 1 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_eq +; CHECK-NEXT: icmp eq i8 %a, 7 +define i1 @nonexact_ashr_eq(i8 %a) { + %shr = ashr i8 -128, %a + %cmp = icmp eq i8 %shr, -1 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_ne +; CHECK-NEXT: icmp ne i8 %a, 7 +define i1 @nonexact_ashr_ne(i8 %a) { + %shr = ashr i8 -128, %a + %cmp = icmp ne i8 %shr, -1 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_eq +; CHECK-NEXT: icmp eq i8 %a, 2 +define i1 @nonexact_lshr_eq(i8 %a) { + %shr = lshr i8 4, %a + %cmp = icmp eq i8 %shr, 1 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_ne +; CHECK-NEXT: icmp ne i8 %a, 2 +define i1 @nonexact_lshr_ne(i8 %a) { + %shr = lshr i8 4, %a + %cmp = icmp ne i8 %shr, 1 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_eq_exactdiv +; CHECK-NEXT: icmp eq i8 %a, 4 +define i1 @exact_lshr_eq_exactdiv(i8 %a) { + %shr = lshr exact i8 80, %a + %cmp = icmp eq i8 %shr, 5 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_ne_exactdiv +; CHECK-NEXT: icmp ne i8 %a, 4 +define i1 @exact_lshr_ne_exactdiv(i8 %a) { + %shr = lshr exact i8 80, %a + %cmp = icmp ne i8 %shr, 5 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_eq_exactdiv +; CHECK-NEXT: icmp eq i8 %a, 4 +define i1 @nonexact_lshr_eq_exactdiv(i8 %a) { + %shr = lshr i8 80, %a + %cmp = icmp eq i8 %shr, 5 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_ne_exactdiv +; CHECK-NEXT: icmp ne i8 %a, 4 +define i1 @nonexact_lshr_ne_exactdiv(i8 %a) { + %shr = lshr i8 80, %a + %cmp = icmp ne i8 %shr, 5 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_eq_exactdiv +; CHECK-NEXT: icmp eq i8 %a, 4 +define i1 @exact_ashr_eq_exactdiv(i8 %a) { + %shr = ashr exact i8 -80, %a + %cmp = icmp eq i8 %shr, -5 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_ne_exactdiv +; CHECK-NEXT: icmp ne i8 %a, 4 +define i1 @exact_ashr_ne_exactdiv(i8 %a) { + %shr = ashr exact i8 -80, %a + %cmp = icmp ne i8 %shr, -5 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_eq_exactdiv +; CHECK-NEXT: icmp eq i8 %a, 4 +define i1 @nonexact_ashr_eq_exactdiv(i8 %a) { + %shr = ashr i8 -80, %a + %cmp = icmp eq i8 %shr, -5 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_ne_exactdiv +; CHECK-NEXT: icmp ne i8 %a, 4 +define i1 @nonexact_ashr_ne_exactdiv(i8 %a) { + %shr = ashr i8 -80, %a + %cmp = icmp ne i8 %shr, -5 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_eq_noexactdiv +; CHECK-NEXT: ret i1 false +define i1 @exact_lshr_eq_noexactdiv(i8 %a) { + %shr = lshr exact i8 80, %a + %cmp = icmp eq i8 %shr, 31 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_ne_noexactdiv +; CHECK-NEXT: ret i1 true +define i1 @exact_lshr_ne_noexactdiv(i8 %a) { + %shr = lshr exact i8 80, %a + %cmp = icmp ne i8 %shr, 31 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_eq_noexactdiv +; CHECK-NEXT: ret i1 false +define i1 @nonexact_lshr_eq_noexactdiv(i8 %a) { + %shr = lshr i8 80, %a + %cmp = icmp eq i8 %shr, 31 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_ne_noexactdiv +; CHECK-NEXT: ret i1 true +define i1 @nonexact_lshr_ne_noexactdiv(i8 %a) { + %shr = lshr i8 80, %a + %cmp = icmp ne i8 %shr, 31 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_eq_noexactdiv +; CHECK-NEXT: ret i1 false +define i1 @exact_ashr_eq_noexactdiv(i8 %a) { + %shr = ashr exact i8 -80, %a + %cmp = icmp eq i8 %shr, -31 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_ne_noexactdiv +; CHECK-NEXT: ret i1 true +define i1 @exact_ashr_ne_noexactdiv(i8 %a) { + %shr = ashr exact i8 -80, %a + %cmp = icmp ne i8 %shr, -31 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_eq_noexactdiv +; CHECK-NEXT: ret i1 false +define i1 @nonexact_ashr_eq_noexactdiv(i8 %a) { + %shr = ashr i8 -80, %a + %cmp = icmp eq i8 %shr, -31 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_ne_noexactdiv +; CHECK-NEXT: ret i1 true +define i1 @nonexact_ashr_ne_noexactdiv(i8 %a) { + %shr = ashr i8 -80, %a + %cmp = icmp ne i8 %shr, -31 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_eq_noexactlog +; CHECK-NEXT: ret i1 false +define i1 @nonexact_lshr_eq_noexactlog(i8 %a) { + %shr = lshr i8 90, %a + %cmp = icmp eq i8 %shr, 30 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_ne_noexactlog +; CHECK-NEXT: ret i1 true +define i1 @nonexact_lshr_ne_noexactlog(i8 %a) { + %shr = lshr i8 90, %a + %cmp = icmp ne i8 %shr, 30 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_eq_noexactlog +; CHECK-NEXT: ret i1 false +define i1 @nonexact_ashr_eq_noexactlog(i8 %a) { + %shr = ashr i8 -90, %a + %cmp = icmp eq i8 %shr, -30 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_ne_noexactlog +; CHECK-NEXT: ret i1 true +define i1 @nonexact_ashr_ne_noexactlog(i8 %a) { + %shr = ashr i8 -90, %a + %cmp = icmp ne i8 %shr, -30 + ret i1 %cmp +} + +; Don't try to fold the entire body of function @PR20945 into a +; single `ret i1 true` statement. +; If %B is equal to 1, then this function would return false. +; As a consequence, the instruction combiner is not allowed to fold %cmp +; to 'true'. Instead, it should replace %cmp with a simpler comparison +; between %B and 1. + +; CHECK-LABEL: @PR20945( +; CHECK: icmp ne i32 %B, 1 +define i1 @PR20945(i32 %B) { + %shr = ashr i32 -9, %B + %cmp = icmp ne i32 %shr, -5 + ret i1 %cmp +} + +; CHECK-LABEL: @PR21222 +; CHECK: icmp eq i32 %B, 6 +define i1 @PR21222(i32 %B) { + %shr = ashr i32 -93, %B + %cmp = icmp eq i32 %shr, -2 + ret i1 %cmp +} diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index 26e144f93a57..64741c5712eb 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -1148,22 +1148,6 @@ define i1 @icmp_shl_1_V_eq_32(i32 %V) { ret i1 %cmp } -; CHECK-LABEL: @icmp_shl_1_V_eq_31( -; CHECK-NEXT: ret i1 false -define i1 @icmp_shl_1_V_eq_31(i32 %V) { - %shl = shl i32 1, %V - %cmp = icmp eq i32 %shl, 31 - ret i1 %cmp -} - -; CHECK-LABEL: @icmp_shl_1_V_ne_31( -; CHECK-NEXT: ret i1 true -define i1 @icmp_shl_1_V_ne_31(i32 %V) { - %shl = shl i32 1, %V - %cmp = icmp ne i32 %shl, 31 - ret i1 %cmp -} - ; CHECK-LABEL: @icmp_shl_1_V_ult_30( ; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ult i32 %V, 5 ; CHECK-NEXT: ret i1 [[CMP]] @@ -1209,22 +1193,6 @@ define i1 @icmp_shl_1_V_uge_2147483648(i32 %V) { ret i1 %cmp } -; CHECK-LABEL: @icmp_shl_1_V_ugt_2147483648( -; CHECK-NEXT: ret i1 false -define i1 @icmp_shl_1_V_ugt_2147483648(i32 %V) { - %shl = shl i32 1, %V - %cmp = icmp ugt i32 %shl, 2147483648 - ret i1 %cmp -} - -; CHECK-LABEL: @icmp_shl_1_V_ule_2147483648( -; CHECK-NEXT: ret i1 true -define i1 @icmp_shl_1_V_ule_2147483648(i32 %V) { - %shl = shl i32 1, %V - %cmp = icmp ule i32 %shl, 2147483648 - ret i1 %cmp -} - ; CHECK-LABEL: @icmp_shl_1_V_ult_2147483648( ; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 %V, 31 ; CHECK-NEXT: ret i1 [[CMP]] @@ -1424,3 +1392,184 @@ define i1 @icmp_neg_cst_slt(i32 %a) { %2 = icmp slt i32 %1, -10 ret i1 %2 } + +; CHECK-LABEL: @icmp_and_or_lshr +; CHECK-NEXT: [[SHL:%[a-z0-9]+]] = shl nuw i32 1, %y +; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 [[SHL]], 1 +; CHECK-NEXT: [[AND:%[a-z0-9]+]] = and i32 [[OR]], %x +; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 [[AND]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +define i1 @icmp_and_or_lshr(i32 %x, i32 %y) { + %shf = lshr i32 %x, %y + %or = or i32 %shf, %x + %and = and i32 %or, 1 + %ret = icmp ne i32 %and, 0 + ret i1 %ret +} + +; CHECK-LABEL: @icmp_and_or_lshr_cst +; CHECK-NEXT: [[AND:%[a-z0-9]+]] = and i32 %x, 3 +; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 [[AND]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +define i1 @icmp_and_or_lshr_cst(i32 %x) { + %shf = lshr i32 %x, 1 + %or = or i32 %shf, %x + %and = and i32 %or, 1 + %ret = icmp ne i32 %and, 0 + ret i1 %ret +} + +; CHECK-LABEL: @shl_ap1_zero_ap2_non_zero_2 +; CHECK-NEXT: %cmp = icmp ugt i32 %a, 29 +; CHECK-NEXT: ret i1 %cmp +define i1 @shl_ap1_zero_ap2_non_zero_2(i32 %a) { + %shl = shl i32 4, %a + %cmp = icmp eq i32 %shl, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @shl_ap1_zero_ap2_non_zero_4 +; CHECK-NEXT: %cmp = icmp ugt i32 %a, 30 +; CHECK-NEXT: ret i1 %cmp +define i1 @shl_ap1_zero_ap2_non_zero_4(i32 %a) { + %shl = shl i32 -2, %a + %cmp = icmp eq i32 %shl, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @shl_ap1_non_zero_ap2_non_zero_both_positive +; CHECK-NEXT: %cmp = icmp eq i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp +define i1 @shl_ap1_non_zero_ap2_non_zero_both_positive(i32 %a) { + %shl = shl i32 50, %a + %cmp = icmp eq i32 %shl, 50 + ret i1 %cmp +} + +; CHECK-LABEL: @shl_ap1_non_zero_ap2_non_zero_both_negative +; CHECK-NEXT: %cmp = icmp eq i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp +define i1 @shl_ap1_non_zero_ap2_non_zero_both_negative(i32 %a) { + %shl = shl i32 -50, %a + %cmp = icmp eq i32 %shl, -50 + ret i1 %cmp +} + +; CHECK-LABEL: @shl_ap1_non_zero_ap2_non_zero_ap1_1 +; CHECK-NEXT: ret i1 false +define i1 @shl_ap1_non_zero_ap2_non_zero_ap1_1(i32 %a) { + %shl = shl i32 50, %a + %cmp = icmp eq i32 %shl, 25 + ret i1 %cmp +} + +; CHECK-LABEL: @shl_ap1_non_zero_ap2_non_zero_ap1_2 +; CHECK-NEXT: %cmp = icmp eq i32 %a, 1 +; CHECK-NEXT: ret i1 %cmp +define i1 @shl_ap1_non_zero_ap2_non_zero_ap1_2(i32 %a) { + %shl = shl i32 25, %a + %cmp = icmp eq i32 %shl, 50 + ret i1 %cmp +} + +; CHECK-LABEL: @shl_ap1_non_zero_ap2_non_zero_ap1_3 +; CHECK-NEXT: ret i1 false +define i1 @shl_ap1_non_zero_ap2_non_zero_ap1_3(i32 %a) { + %shl = shl i32 26, %a + %cmp = icmp eq i32 %shl, 50 + ret i1 %cmp +} + +; CHECK-LABEL: @icmp_sgt_zero_add_nsw +; CHECK-NEXT: icmp sgt i32 %a, -1 +define i1 @icmp_sgt_zero_add_nsw(i32 %a) { + %add = add nsw i32 %a, 1 + %cmp = icmp sgt i32 %add, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @icmp_sge_zero_add_nsw +; CHECK-NEXT: icmp sgt i32 %a, -2 +define i1 @icmp_sge_zero_add_nsw(i32 %a) { + %add = add nsw i32 %a, 1 + %cmp = icmp sge i32 %add, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @icmp_slt_zero_add_nsw +; CHECK-NEXT: icmp slt i32 %a, -1 +define i1 @icmp_slt_zero_add_nsw(i32 %a) { + %add = add nsw i32 %a, 1 + %cmp = icmp slt i32 %add, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @icmp_sle_zero_add_nsw +; CHECK-NEXT: icmp slt i32 %a, 0 +define i1 @icmp_sle_zero_add_nsw(i32 %a) { + %add = add nsw i32 %a, 1 + %cmp = icmp sle i32 %add, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @icmp_cmpxchg_strong +; CHECK-NEXT: %[[xchg:.*]] = cmpxchg i32* %sc, i32 %old_val, i32 %new_val seq_cst seq_cst +; CHECK-NEXT: %[[icmp:.*]] = extractvalue { i32, i1 } %[[xchg]], 1 +; CHECK-NEXT: ret i1 %[[icmp]] +define zeroext i1 @icmp_cmpxchg_strong(i32* %sc, i32 %old_val, i32 %new_val) { + %xchg = cmpxchg i32* %sc, i32 %old_val, i32 %new_val seq_cst seq_cst + %xtrc = extractvalue { i32, i1 } %xchg, 0 + %icmp = icmp eq i32 %xtrc, %old_val + ret i1 %icmp +} + +; CHECK-LABEL: @f1 +; CHECK-NEXT: %[[cmp:.*]] = icmp sge i64 %a, %b +; CHECK-NEXT: ret i1 %[[cmp]] +define i1 @f1(i64 %a, i64 %b) { + %t = sub nsw i64 %a, %b + %v = icmp sge i64 %t, 0 + ret i1 %v +} + +; CHECK-LABEL: @f2 +; CHECK-NEXT: %[[cmp:.*]] = icmp sgt i64 %a, %b +; CHECK-NEXT: ret i1 %[[cmp]] +define i1 @f2(i64 %a, i64 %b) { + %t = sub nsw i64 %a, %b + %v = icmp sgt i64 %t, 0 + ret i1 %v +} + +; CHECK-LABEL: @f3 +; CHECK-NEXT: %[[cmp:.*]] = icmp slt i64 %a, %b +; CHECK-NEXT: ret i1 %[[cmp]] +define i1 @f3(i64 %a, i64 %b) { + %t = sub nsw i64 %a, %b + %v = icmp slt i64 %t, 0 + ret i1 %v +} + +; CHECK-LABEL: @f4 +; CHECK-NEXT: %[[cmp:.*]] = icmp sle i64 %a, %b +; CHECK-NEXT: ret i1 %[[cmp]] +define i1 @f4(i64 %a, i64 %b) { + %t = sub nsw i64 %a, %b + %v = icmp sle i64 %t, 0 + ret i1 %v +} + +; CHECK-LABEL: @f5 +; CHECK: %[[cmp:.*]] = icmp slt i32 %[[sub:.*]], 0 +; CHECK: %[[neg:.*]] = sub nsw i32 0, %[[sub]] +; CHECK: %[[sel:.*]] = select i1 %[[cmp]], i32 %[[neg]], i32 %[[sub]] +; CHECK: ret i32 %[[sel]] +define i32 @f5(i8 %a, i8 %b) { + %conv = zext i8 %a to i32 + %conv3 = zext i8 %b to i32 + %sub = sub nsw i32 %conv, %conv3 + %cmp4 = icmp slt i32 %sub, 0 + %sub7 = sub nsw i32 0, %sub + %sub7.sub = select i1 %cmp4, i32 %sub7, i32 %sub + ret i32 %sub7.sub +} diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll index 9b58d9386f58..8e7742f8c34a 100644 --- a/test/Transforms/InstCombine/intrinsics.ll +++ b/test/Transforms/InstCombine/intrinsics.ll @@ -1,10 +1,17 @@ ; RUN: opt -instcombine -S < %s | FileCheck %s %overflow.result = type {i8, i1} +%ov.result.32 = type { i32, i1 } + -declare %overflow.result @llvm.uadd.with.overflow.i8(i8, i8) -declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) -declare %overflow.result @llvm.umul.with.overflow.i8(i8, i8) +declare %overflow.result @llvm.uadd.with.overflow.i8(i8, i8) nounwind readnone +declare %overflow.result @llvm.umul.with.overflow.i8(i8, i8) nounwind readnone +declare %ov.result.32 @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone +declare %ov.result.32 @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone +declare %ov.result.32 @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone +declare %ov.result.32 @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone +declare %ov.result.32 @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone +declare %ov.result.32 @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone declare double @llvm.powi.f64(double, i32) nounwind readonly declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone @@ -91,17 +98,92 @@ define i8 @uaddtest7(i8 %A, i8 %B) { } ; PR20194 -define { i32, i1 } @saddtest1(i8 %a, i8 %b) { +define %ov.result.32 @saddtest_nsw(i8 %a, i8 %b) { %A = sext i8 %a to i32 %B = sext i8 %b to i32 - %x = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %A, i32 %B) - ret { i32, i1 } %x -; CHECK-LABEL: @saddtest1 + %x = call %ov.result.32 @llvm.sadd.with.overflow.i32(i32 %A, i32 %B) + ret %ov.result.32 %x +; CHECK-LABEL: @saddtest_nsw ; CHECK: %x = add nsw i32 %A, %B -; CHECK-NEXT: %1 = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 %x, 0 -; CHECK-NEXT: ret { i32, i1 } %1 +; CHECK-NEXT: %1 = insertvalue %ov.result.32 { i32 undef, i1 false }, i32 %x, 0 +; CHECK-NEXT: ret %ov.result.32 %1 +} + +define %ov.result.32 @uaddtest_nuw(i32 %a, i32 %b) { + %A = and i32 %a, 2147483647 + %B = and i32 %b, 2147483647 + %x = call %ov.result.32 @llvm.uadd.with.overflow.i32(i32 %A, i32 %B) + ret %ov.result.32 %x +; CHECK-LABEL: @uaddtest_nuw +; CHECK: %x = add nuw i32 %A, %B +; CHECK-NEXT: %1 = insertvalue %ov.result.32 { i32 undef, i1 false }, i32 %x, 0 +; CHECK-NEXT: ret %ov.result.32 %1 +} + +define %ov.result.32 @ssubtest_nsw(i8 %a, i8 %b) { + %A = sext i8 %a to i32 + %B = sext i8 %b to i32 + %x = call %ov.result.32 @llvm.ssub.with.overflow.i32(i32 %A, i32 %B) + ret %ov.result.32 %x +; CHECK-LABEL: @ssubtest_nsw +; CHECK: %x = sub nsw i32 %A, %B +; CHECK-NEXT: %1 = insertvalue %ov.result.32 { i32 undef, i1 false }, i32 %x, 0 +; CHECK-NEXT: ret %ov.result.32 %1 } +define %ov.result.32 @usubtest_nuw(i32 %a, i32 %b) { + %A = or i32 %a, 2147483648 + %B = and i32 %b, 2147483647 + %x = call %ov.result.32 @llvm.usub.with.overflow.i32(i32 %A, i32 %B) + ret %ov.result.32 %x +; CHECK-LABEL: @usubtest_nuw +; CHECK: %x = sub nuw i32 %A, %B +; CHECK-NEXT: %1 = insertvalue %ov.result.32 { i32 undef, i1 false }, i32 %x, 0 +; CHECK-NEXT: ret %ov.result.32 %1 +} + +define %ov.result.32 @smultest1_nsw(i32 %a, i32 %b) { + %A = and i32 %a, 4095 ; 0xfff + %B = and i32 %b, 524287; 0x7ffff + %x = call %ov.result.32 @llvm.smul.with.overflow.i32(i32 %A, i32 %B) + ret %ov.result.32 %x +; CHECK-LABEL: @smultest1_nsw +; CHECK: %x = mul nuw nsw i32 %A, %B +; CHECK-NEXT: %1 = insertvalue %ov.result.32 { i32 undef, i1 false }, i32 %x, 0 +; CHECK-NEXT: ret %ov.result.32 %1 +} + +define %ov.result.32 @smultest2_nsw(i32 %a, i32 %b) { + %A = ashr i32 %a, 16 + %B = ashr i32 %b, 16 + %x = call %ov.result.32 @llvm.smul.with.overflow.i32(i32 %A, i32 %B) + ret %ov.result.32 %x +; CHECK-LABEL: @smultest2_nsw +; CHECK: %x = mul nsw i32 %A, %B +; CHECK-NEXT: %1 = insertvalue %ov.result.32 { i32 undef, i1 false }, i32 %x, 0 +; CHECK-NEXT: ret %ov.result.32 %1 +} + +define %ov.result.32 @smultest3_sw(i32 %a, i32 %b) { + %A = ashr i32 %a, 16 + %B = ashr i32 %b, 15 + %x = call %ov.result.32 @llvm.smul.with.overflow.i32(i32 %A, i32 %B) + ret %ov.result.32 %x +; CHECK-LABEL: @smultest3_sw +; CHECK: %x = call %ov.result.32 @llvm.smul.with.overflow.i32(i32 %A, i32 %B) +; CHECK-NEXT: ret %ov.result.32 %x +} + +define %ov.result.32 @umultest_nuw(i32 %a, i32 %b) { + %A = and i32 %a, 65535 ; 0xffff + %B = and i32 %b, 65535 ; 0xffff + %x = call %ov.result.32 @llvm.umul.with.overflow.i32(i32 %A, i32 %B) + ret %ov.result.32 %x +; CHECK-LABEL: @umultest_nuw +; CHECK: %x = mul nuw i32 %A, %B +; CHECK-NEXT: %1 = insertvalue %ov.result.32 { i32 undef, i1 false }, i32 %x, 0 +; CHECK-NEXT: ret %ov.result.32 %1 +} define i8 @umultest1(i8 %A, i1* %overflowPtr) { %x = call %overflow.result @llvm.umul.with.overflow.i8(i8 0, i8 %A) @@ -125,9 +207,6 @@ define i8 @umultest2(i8 %A, i1* %overflowPtr) { ; CHECK-NEXT: ret i8 %A } -%ov.result.32 = type { i32, i1 } -declare %ov.result.32 @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone - define i32 @umultest3(i32 %n) nounwind { %shr = lshr i32 %n, 2 %mul = call %ov.result.32 @llvm.umul.with.overflow.i32(i32 %shr, i32 3) @@ -152,6 +231,19 @@ define i32 @umultest4(i32 %n) nounwind { ; CHECK: umul.with.overflow } +define %ov.result.32 @umultest5(i32 %x, i32 %y) nounwind { + %or_x = or i32 %x, 2147483648 + %or_y = or i32 %y, 2147483648 + %mul = call %ov.result.32 @llvm.umul.with.overflow.i32(i32 %or_x, i32 %or_y) + ret %ov.result.32 %mul +; CHECK-LABEL: @umultest5( +; CHECK-NEXT: %[[or_x:.*]] = or i32 %x, -2147483648 +; CHECK-NEXT: %[[or_y:.*]] = or i32 %y, -2147483648 +; CHECK-NEXT: %[[mul:.*]] = mul i32 %[[or_x]], %[[or_y]] +; CHECK-NEXT: %[[ret:.*]] = insertvalue %ov.result.32 { i32 undef, i1 true }, i32 %[[mul]], 0 +; CHECK-NEXT: ret %ov.result.32 %[[ret]] +} + define void @powi(double %V, double *%P) { entry: %A = tail call double @llvm.powi.f64(double %V, i32 -1) nounwind diff --git a/test/Transforms/InstCombine/load-addrspace-cast.ll b/test/Transforms/InstCombine/load-addrspace-cast.ll deleted file mode 100644 index fd6339cc9262..000000000000 --- a/test/Transforms/InstCombine/load-addrspace-cast.ll +++ /dev/null @@ -1,12 +0,0 @@ -; RUN: opt -instcombine -S < %s | FileCheck %s -target datalayout = "e-p:64:64:64-n8:16:32:64" - -define i32* @pointer_to_addrspace_pointer(i32 addrspace(1)** %x) nounwind { -; CHECK-LABEL: @pointer_to_addrspace_pointer( -; CHECK: load -; CHECK: addrspacecast - %y = bitcast i32 addrspace(1)** %x to i32** - %z = load i32** %y - ret i32* %z -} - diff --git a/test/Transforms/InstCombine/load.ll b/test/Transforms/InstCombine/load.ll index c8ce70a5c03a..b4b7558a1a05 100644 --- a/test/Transforms/InstCombine/load.ll +++ b/test/Transforms/InstCombine/load.ll @@ -2,6 +2,7 @@ ; This test makes sure that these instructions are properly eliminated. +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" @X = constant i32 42 ; <i32*> [#uses=2] @X2 = constant i32 47 ; <i32*> [#uses=1] @@ -118,3 +119,34 @@ define <16 x i8> @test13(<2 x i64> %x) { %tmp = load <16 x i8>* bitcast ([4 x i32]* @GLOBAL to <16 x i8>*) ret <16 x i8> %tmp } + +define i8 @test14(i8 %x, i32 %y) { +; This test must not have the store of %x forwarded to the load -- there is an +; intervening store if %y. However, the intervening store occurs with a different +; type and size and to a different pointer value. This is ensuring that none of +; those confuse the analysis into thinking that the second store does not alias +; the first. +; CHECK-LABEL: @test14( +; CHECK: %[[R:.*]] = load i8* +; CHECK-NEXT: ret i8 %[[R]] + %a = alloca i32 + %a.i8 = bitcast i32* %a to i8* + store i8 %x, i8* %a.i8 + store i32 %y, i32* %a + %r = load i8* %a.i8 + ret i8 %r +} + +@test15_global = external global i32 + +define i8 @test15(i8 %x, i32 %y) { +; Same test as @test14 essentially, but using a global instead of an alloca. +; CHECK-LABEL: @test15( +; CHECK: %[[R:.*]] = load i8* +; CHECK-NEXT: ret i8 %[[R]] + %g.i8 = bitcast i32* @test15_global to i8* + store i8 %x, i8* %g.i8 + store i32 %y, i32* @test15_global + %r = load i8* %g.i8 + ret i8 %r +} diff --git a/test/Transforms/InstCombine/loadstore-metadata.ll b/test/Transforms/InstCombine/loadstore-metadata.ll new file mode 100644 index 000000000000..ad6a11cf6eb1 --- /dev/null +++ b/test/Transforms/InstCombine/loadstore-metadata.ll @@ -0,0 +1,86 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +define i32 @test_load_cast_combine_tbaa(float* %ptr) { +; Ensure (cast (load (...))) -> (load (cast (...))) preserves TBAA. +; CHECK-LABEL: @test_load_cast_combine_tbaa( +; CHECK: load i32* %{{.*}}, !tbaa !0 +entry: + %l = load float* %ptr, !tbaa !0 + %c = bitcast float %l to i32 + ret i32 %c +} + +define i32 @test_load_cast_combine_noalias(float* %ptr) { +; Ensure (cast (load (...))) -> (load (cast (...))) preserves no-alias metadata. +; CHECK-LABEL: @test_load_cast_combine_noalias( +; CHECK: load i32* %{{.*}}, !alias.scope !2, !noalias !1 +entry: + %l = load float* %ptr, !alias.scope !2, !noalias !1 + %c = bitcast float %l to i32 + ret i32 %c +} + +define float @test_load_cast_combine_range(i32* %ptr) { +; Ensure (cast (load (...))) -> (load (cast (...))) drops range metadata. It +; would be nice to preserve or update it somehow but this is hard when moving +; between types. +; CHECK-LABEL: @test_load_cast_combine_range( +; CHECK: load float* %{{.*}} +; CHECK-NOT: !range +; CHECK: ret float +entry: + %l = load i32* %ptr, !range !5 + %c = bitcast i32 %l to float + ret float %c +} + +define i32 @test_load_cast_combine_invariant(float* %ptr) { +; Ensure (cast (load (...))) -> (load (cast (...))) preserves invariant metadata. +; CHECK-LABEL: @test_load_cast_combine_invariant( +; CHECK: load i32* %{{.*}}, !invariant.load !3 +entry: + %l = load float* %ptr, !invariant.load !3 + %c = bitcast float %l to i32 + ret i32 %c +} + +define i32 @test_load_cast_combine_nontemporal(float* %ptr) { +; Ensure (cast (load (...))) -> (load (cast (...))) preserves nontemporal +; metadata. +; CHECK-LABEL: @test_load_cast_combine_nontemporal( +; CHECK: load i32* %{{.*}}, !nontemporal !4 +entry: + %l = load float* %ptr, !nontemporal !4 + %c = bitcast float %l to i32 + ret i32 %c +} + +define void @test_load_cast_combine_loop(float* %src, i32* %dst, i32 %n) { +; Ensure (cast (load (...))) -> (load (cast (...))) preserves loop access +; metadata. +; CHECK-LABEL: @test_load_cast_combine_loop( +; CHECK: load i32* %{{.*}}, !llvm.mem.parallel_loop_access !1 +entry: + br label %loop + +loop: + %i = phi i32 [ 0, %entry ], [ %i.next, %loop ] + %src.gep = getelementptr inbounds float* %src, i32 %i + %dst.gep = getelementptr inbounds i32* %dst, i32 %i + %l = load float* %src.gep, !llvm.mem.parallel_loop_access !1 + %c = bitcast float %l to i32 + store i32 %c, i32* %dst.gep + %i.next = add i32 %i, 1 + %cmp = icmp slt i32 %i.next, %n + br i1 %cmp, label %loop, label %exit, !llvm.loop !1 + +exit: + ret void +} + +!0 = !{ !1, !1, i64 0 } +!1 = !{ !1 } +!2 = !{ !2, !1 } +!3 = !{ } +!4 = !{ i32 1 } +!5 = !{ i32 0, i32 42 } diff --git a/test/Transforms/InstCombine/malloc-free-delete.ll b/test/Transforms/InstCombine/malloc-free-delete.ll index 208520653848..ed25e4e49c84 100644 --- a/test/Transforms/InstCombine/malloc-free-delete.ll +++ b/test/Transforms/InstCombine/malloc-free-delete.ll @@ -144,3 +144,26 @@ lpad.i: ; preds = %entry call void @_ZdlPvRKSt9nothrow_t(i8* %call.i, i8* %nt) builtin nounwind resume { i8*, i32 } %0 } + +declare i8* @_Znwm(i64) nobuiltin +declare void @_ZdlPvm(i8*, i64) nobuiltin +declare i8* @_Znwj(i32) nobuiltin +declare void @_ZdlPvj(i8*, i32) nobuiltin +declare i8* @_Znam(i64) nobuiltin +declare void @_ZdaPvm(i8*, i64) nobuiltin +declare i8* @_Znaj(i32) nobuiltin +declare void @_ZdaPvj(i8*, i32) nobuiltin + +; CHECK-LABEL: @test8( +define void @test8() { + ; CHECK-NOT: call + %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 + ret void +} diff --git a/test/Transforms/InstCombine/maxnum.ll b/test/Transforms/InstCombine/maxnum.ll new file mode 100644 index 000000000000..585d9f41f9fc --- /dev/null +++ b/test/Transforms/InstCombine/maxnum.ll @@ -0,0 +1,222 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +declare float @llvm.maxnum.f32(float, float) #0 +declare float @llvm.maxnum.v2f32(<2 x float>, <2 x float>) #0 +declare <4 x float> @llvm.maxnum.v4f32(<4 x float>, <4 x float>) #0 + +declare double @llvm.maxnum.f64(double, double) #0 +declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>) #0 + +; CHECK-LABEL: @constant_fold_maxnum_f32 +; CHECK-NEXT: ret float 2.000000e+00 +define float @constant_fold_maxnum_f32() #0 { + %x = call float @llvm.maxnum.f32(float 1.0, float 2.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_maxnum_f32_inv +; CHECK-NEXT: ret float 2.000000e+00 +define float @constant_fold_maxnum_f32_inv() #0 { + %x = call float @llvm.maxnum.f32(float 2.0, float 1.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_maxnum_f32_nan0 +; CHECK-NEXT: ret float 2.000000e+00 +define float @constant_fold_maxnum_f32_nan0() #0 { + %x = call float @llvm.maxnum.f32(float 0x7FF8000000000000, float 2.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_maxnum_f32_nan1 +; CHECK-NEXT: ret float 2.000000e+00 +define float @constant_fold_maxnum_f32_nan1() #0 { + %x = call float @llvm.maxnum.f32(float 2.0, float 0x7FF8000000000000) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_maxnum_f32_nan_nan +; CHECK-NEXT: ret float 0x7FF8000000000000 +define float @constant_fold_maxnum_f32_nan_nan() #0 { + %x = call float @llvm.maxnum.f32(float 0x7FF8000000000000, float 0x7FF8000000000000) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_maxnum_f32_p0_p0 +; CHECK-NEXT: ret float 0.000000e+00 +define float @constant_fold_maxnum_f32_p0_p0() #0 { + %x = call float @llvm.maxnum.f32(float 0.0, float 0.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_maxnum_f32_p0_n0 +; CHECK-NEXT: ret float 0.000000e+00 +define float @constant_fold_maxnum_f32_p0_n0() #0 { + %x = call float @llvm.maxnum.f32(float 0.0, float -0.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_maxnum_f32_n0_p0 +; CHECK-NEXT: ret float -0.000000e+00 +define float @constant_fold_maxnum_f32_n0_p0() #0 { + %x = call float @llvm.maxnum.f32(float -0.0, float 0.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_maxnum_f32_n0_n0 +; CHECK-NEXT: ret float -0.000000e+00 +define float @constant_fold_maxnum_f32_n0_n0() #0 { + %x = call float @llvm.maxnum.f32(float -0.0, float -0.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_maxnum_v4f32 +; CHECK-NEXT: ret <4 x float> <float 2.000000e+00, float 8.000000e+00, float 1.000000e+01, float 9.000000e+00> +define <4 x float> @constant_fold_maxnum_v4f32() #0 { + %x = call <4 x float> @llvm.maxnum.v4f32(<4 x float> <float 1.0, float 8.0, float 3.0, float 9.0>, <4 x float> <float 2.0, float 2.0, float 10.0, float 5.0>) + ret <4 x float> %x +} + +; CHECK-LABEL: @constant_fold_maxnum_f64 +; CHECK-NEXT: ret double 2.000000e+00 +define double @constant_fold_maxnum_f64() #0 { + %x = call double @llvm.maxnum.f64(double 1.0, double 2.0) #0 + ret double %x +} + +; CHECK-LABEL: @constant_fold_maxnum_f64_nan0 +; CHECK-NEXT: ret double 2.000000e+00 +define double @constant_fold_maxnum_f64_nan0() #0 { + %x = call double @llvm.maxnum.f64(double 0x7FF8000000000000, double 2.0) #0 + ret double %x +} + +; CHECK-LABEL: @constant_fold_maxnum_f64_nan1 +; CHECK-NEXT: ret double 2.000000e+00 +define double @constant_fold_maxnum_f64_nan1() #0 { + %x = call double @llvm.maxnum.f64(double 2.0, double 0x7FF8000000000000) #0 + ret double %x +} + +; CHECK-LABEL: @constant_fold_maxnum_f64_nan_nan +; CHECK-NEXT: ret double 0x7FF8000000000000 +define double @constant_fold_maxnum_f64_nan_nan() #0 { + %x = call double @llvm.maxnum.f64(double 0x7FF8000000000000, double 0x7FF8000000000000) #0 + ret double %x +} + +; CHECK-LABEL: @canonicalize_constant_maxnum_f32 +; CHECK: call float @llvm.maxnum.f32(float %x, float 1.000000e+00) +define float @canonicalize_constant_maxnum_f32(float %x) #0 { + %y = call float @llvm.maxnum.f32(float 1.0, float %x) #0 + ret float %y +} + +; CHECK-LABEL: @noop_maxnum_f32 +; CHECK-NEXT: ret float %x +define float @noop_maxnum_f32(float %x) #0 { + %y = call float @llvm.maxnum.f32(float %x, float %x) #0 + ret float %y +} + +; CHECK-LABEL: @maxnum_f32_nan_val +; CHECK-NEXT: ret float %x +define float @maxnum_f32_nan_val(float %x) #0 { + %y = call float @llvm.maxnum.f32(float 0x7FF8000000000000, float %x) #0 + ret float %y +} + +; CHECK-LABEL: @maxnum_f32_val_nan +; CHECK-NEXT: ret float %x +define float @maxnum_f32_val_nan(float %x) #0 { + %y = call float @llvm.maxnum.f32(float %x, float 0x7FF8000000000000) #0 + ret float %y +} + +; CHECK-LABEL: @fold_maxnum_f32_undef_undef +; CHECK-NEXT: ret float undef +define float @fold_maxnum_f32_undef_undef(float %x) nounwind { + %val = call float @llvm.maxnum.f32(float undef, float undef) #0 + ret float %val +} + +; CHECK-LABEL: @fold_maxnum_f32_val_undef +; CHECK-NEXT: ret float %x +define float @fold_maxnum_f32_val_undef(float %x) nounwind { + %val = call float @llvm.maxnum.f32(float %x, float undef) #0 + ret float %val +} + +; CHECK-LABEL: @fold_maxnum_f32_undef_val +; CHECK-NEXT: ret float %x +define float @fold_maxnum_f32_undef_val(float %x) nounwind { + %val = call float @llvm.maxnum.f32(float undef, float %x) #0 + ret float %val +} + +; CHECK-LABEL: @maxnum_x_maxnum_x_y +; CHECK-NEXT: call float @llvm.maxnum.f32(float %x, float %y) +; CHECK-NEXT: ret float +define float @maxnum_x_maxnum_x_y(float %x, float %y) #0 { + %a = call float @llvm.maxnum.f32(float %x, float %y) #0 + %b = call float @llvm.maxnum.f32(float %x, float %a) #0 + ret float %b +} + +; CHECK-LABEL: @maxnum_y_maxnum_x_y +; CHECK-NEXT: call float @llvm.maxnum.f32(float %x, float %y) +; CHECK-NEXT: ret float +define float @maxnum_y_maxnum_x_y(float %x, float %y) #0 { + %a = call float @llvm.maxnum.f32(float %x, float %y) #0 + %b = call float @llvm.maxnum.f32(float %y, float %a) #0 + ret float %b +} + +; CHECK-LABEL: @maxnum_z_maxnum_x_y +; CHECK-NEXT: call float @llvm.maxnum.f32(float %x, float %y) +; CHECK-NEXT: call float @llvm.maxnum.f32(float %z, float %a) +; CHECK-NEXT: ret float +define float @maxnum_z_maxnum_x_y(float %x, float %y, float %z) #0 { + %a = call float @llvm.maxnum.f32(float %x, float %y) #0 + %b = call float @llvm.maxnum.f32(float %z, float %a) #0 + ret float %b +} + +; CHECK-LABEL: @maxnum_maxnum_x_y_z +; CHECK-NEXT: call float @llvm.maxnum.f32(float %x, float %y) +; CHECK-NEXT: call float @llvm.maxnum.f32(float %a, float %z) +; CHECK-NEXT: ret float +define float @maxnum_maxnum_x_y_z(float %x, float %y, float %z) #0 { + %a = call float @llvm.maxnum.f32(float %x, float %y) #0 + %b = call float @llvm.maxnum.f32(float %a, float %z) #0 + ret float %b +} + +; CHECK-LABEL: @maxnum4 +; CHECK-NEXT: call float @llvm.maxnum.f32(float %x, float %y) +; CHECK-NEXT: call float @llvm.maxnum.f32(float %z, float %w) +; CHECK-NEXT: call float @llvm.maxnum.f32(float %a, float %b) +; CHECK-NEXT: ret float +define float @maxnum4(float %x, float %y, float %z, float %w) #0 { + %a = call float @llvm.maxnum.f32(float %x, float %y) #0 + %b = call float @llvm.maxnum.f32(float %z, float %w) #0 + %c = call float @llvm.maxnum.f32(float %a, float %b) #0 + ret float %c +} + +; CHECK-LABEL: @fold_maxnum_f32_inf_val +; CHECK-NEXT: ret float 0x7FF0000000000000 +define float @fold_maxnum_f32_inf_val(float %x) nounwind { + %val = call float @llvm.maxnum.f32(float 0x7FF0000000000000, float %x) #0 + ret float %val +} + +; CHECK-LABEL: @fold_maxnum_f32_neginf_val +; CHECK-NEXT: call float @llvm.maxnum.f32(float %x, float 0xFFF0000000000000) +; CHECK-NEXT: ret float +define float @fold_maxnum_f32_neginf_val(float %x) nounwind { + %val = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float %x) #0 + ret float %val +} + +attributes #0 = { nounwind readnone } diff --git a/test/Transforms/InstCombine/memcmp-1.ll b/test/Transforms/InstCombine/memcmp-1.ll index 65349c6e6906..d960693a05d4 100644 --- a/test/Transforms/InstCombine/memcmp-1.ll +++ b/test/Transforms/InstCombine/memcmp-1.ll @@ -37,7 +37,7 @@ define i32 @test_simplify3(i8* %mem1, i8* %mem2) { ; CHECK: [[ZEXT1:%[a-z]+]] = zext i8 [[LOAD1]] to i32 ; CHECK: [[LOAD2:%[a-z]+]] = load i8* %mem2, align 1 ; CHECK: [[ZEXT2:%[a-z]+]] = zext i8 [[LOAD2]] to i32 -; CHECK: [[RET:%[a-z]+]] = sub i32 [[ZEXT1]], [[ZEXT2]] +; CHECK: [[RET:%[a-z]+]] = sub nsw i32 [[ZEXT1]], [[ZEXT2]] ret i32 %ret ; CHECK: ret i32 [[RET]] } diff --git a/test/Transforms/InstCombine/memcpy_chk-1.ll b/test/Transforms/InstCombine/memcpy_chk-1.ll index 9216ae7fe95a..008b838201ed 100644 --- a/test/Transforms/InstCombine/memcpy_chk-1.ll +++ b/test/Transforms/InstCombine/memcpy_chk-1.ll @@ -57,4 +57,17 @@ define void @test_no_simplify2() { ret void } +define i8* @test_simplify_return_indcall(i8* ()* %alloc) { +; CHECK-LABEL: @test_simplify_return_indcall( + %src = bitcast %struct.T2* @t2 to i8* + +; CHECK-NEXT: %dst = call i8* %alloc() + %dst = call i8* %alloc() + +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64 + %ret = call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1824, i64 1824) +; CHECK-NEXT: ret i8* %dst + ret i8* %ret +} + declare i8* @__memcpy_chk(i8*, i8*, i64, i64) diff --git a/test/Transforms/InstCombine/minnum.ll b/test/Transforms/InstCombine/minnum.ll new file mode 100644 index 000000000000..f7494e7ae154 --- /dev/null +++ b/test/Transforms/InstCombine/minnum.ll @@ -0,0 +1,244 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +declare float @llvm.minnum.f32(float, float) #0 +declare float @llvm.minnum.v2f32(<2 x float>, <2 x float>) #0 +declare <4 x float> @llvm.minnum.v4f32(<4 x float>, <4 x float>) #0 + +declare double @llvm.minnum.f64(double, double) #0 +declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>) #0 + +declare float @llvm.maxnum.f32(float, float) #0 + +; CHECK-LABEL: @constant_fold_minnum_f32 +; CHECK-NEXT: ret float 1.000000e+00 +define float @constant_fold_minnum_f32() #0 { + %x = call float @llvm.minnum.f32(float 1.0, float 2.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_minnum_f32_inv +; CHECK-NEXT: ret float 1.000000e+00 +define float @constant_fold_minnum_f32_inv() #0 { + %x = call float @llvm.minnum.f32(float 2.0, float 1.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_minnum_f32_nan0 +; CHECK-NEXT: ret float 2.000000e+00 +define float @constant_fold_minnum_f32_nan0() #0 { + %x = call float @llvm.minnum.f32(float 0x7FF8000000000000, float 2.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_minnum_f32_nan1 +; CHECK-NEXT: ret float 2.000000e+00 +define float @constant_fold_minnum_f32_nan1() #0 { + %x = call float @llvm.minnum.f32(float 2.0, float 0x7FF8000000000000) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_minnum_f32_nan_nan +; CHECK-NEXT: ret float 0x7FF8000000000000 +define float @constant_fold_minnum_f32_nan_nan() #0 { + %x = call float @llvm.minnum.f32(float 0x7FF8000000000000, float 0x7FF8000000000000) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_minnum_f32_p0_p0 +; CHECK-NEXT: ret float 0.000000e+00 +define float @constant_fold_minnum_f32_p0_p0() #0 { + %x = call float @llvm.minnum.f32(float 0.0, float 0.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_minnum_f32_p0_n0 +; CHECK-NEXT: ret float 0.000000e+00 +define float @constant_fold_minnum_f32_p0_n0() #0 { + %x = call float @llvm.minnum.f32(float 0.0, float -0.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_minnum_f32_n0_p0 +; CHECK-NEXT: ret float -0.000000e+00 +define float @constant_fold_minnum_f32_n0_p0() #0 { + %x = call float @llvm.minnum.f32(float -0.0, float 0.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_minnum_f32_n0_n0 +; CHECK-NEXT: ret float -0.000000e+00 +define float @constant_fold_minnum_f32_n0_n0() #0 { + %x = call float @llvm.minnum.f32(float -0.0, float -0.0) #0 + ret float %x +} + +; CHECK-LABEL: @constant_fold_minnum_v4f32 +; CHECK-NEXT: ret <4 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 5.000000e+00> +define <4 x float> @constant_fold_minnum_v4f32() #0 { + %x = call <4 x float> @llvm.minnum.v4f32(<4 x float> <float 1.0, float 8.0, float 3.0, float 9.0>, <4 x float> <float 2.0, float 2.0, float 10.0, float 5.0>) + ret <4 x float> %x +} + +; CHECK-LABEL: @constant_fold_minnum_f64 +; CHECK-NEXT: ret double 1.000000e+00 +define double @constant_fold_minnum_f64() #0 { + %x = call double @llvm.minnum.f64(double 1.0, double 2.0) #0 + ret double %x +} + +; CHECK-LABEL: @constant_fold_minnum_f64_nan0 +; CHECK-NEXT: ret double 2.000000e+00 +define double @constant_fold_minnum_f64_nan0() #0 { + %x = call double @llvm.minnum.f64(double 0x7FF8000000000000, double 2.0) #0 + ret double %x +} + +; CHECK-LABEL: @constant_fold_minnum_f64_nan1 +; CHECK-NEXT: ret double 2.000000e+00 +define double @constant_fold_minnum_f64_nan1() #0 { + %x = call double @llvm.minnum.f64(double 2.0, double 0x7FF8000000000000) #0 + ret double %x +} + +; CHECK-LABEL: @constant_fold_minnum_f64_nan_nan +; CHECK-NEXT: ret double 0x7FF8000000000000 +define double @constant_fold_minnum_f64_nan_nan() #0 { + %x = call double @llvm.minnum.f64(double 0x7FF8000000000000, double 0x7FF8000000000000) #0 + ret double %x +} + +; CHECK-LABEL: @canonicalize_constant_minnum_f32 +; CHECK: call float @llvm.minnum.f32(float %x, float 1.000000e+00) +define float @canonicalize_constant_minnum_f32(float %x) #0 { + %y = call float @llvm.minnum.f32(float 1.0, float %x) #0 + ret float %y +} + +; CHECK-LABEL: @noop_minnum_f32 +; CHECK-NEXT: ret float %x +define float @noop_minnum_f32(float %x) #0 { + %y = call float @llvm.minnum.f32(float %x, float %x) #0 + ret float %y +} + +; CHECK-LABEL: @minnum_f32_nan_val +; CHECK-NEXT: ret float %x +define float @minnum_f32_nan_val(float %x) #0 { + %y = call float @llvm.minnum.f32(float 0x7FF8000000000000, float %x) #0 + ret float %y +} + +; CHECK-LABEL: @minnum_f32_val_nan +; CHECK-NEXT: ret float %x +define float @minnum_f32_val_nan(float %x) #0 { + %y = call float @llvm.minnum.f32(float %x, float 0x7FF8000000000000) #0 + ret float %y +} + +; CHECK-LABEL: @fold_minnum_f32_undef_undef +; CHECK-NEXT: ret float undef +define float @fold_minnum_f32_undef_undef(float %x) nounwind { + %val = call float @llvm.minnum.f32(float undef, float undef) #0 + ret float %val +} + +; CHECK-LABEL: @fold_minnum_f32_val_undef +; CHECK-NEXT: ret float %x +define float @fold_minnum_f32_val_undef(float %x) nounwind { + %val = call float @llvm.minnum.f32(float %x, float undef) #0 + ret float %val +} + +; CHECK-LABEL: @fold_minnum_f32_undef_val +; CHECK-NEXT: ret float %x +define float @fold_minnum_f32_undef_val(float %x) nounwind { + %val = call float @llvm.minnum.f32(float undef, float %x) #0 + ret float %val +} + +; CHECK-LABEL: @minnum_x_minnum_x_y +; CHECK-NEXT: call float @llvm.minnum.f32(float %x, float %y) +; CHECK-NEXT: ret float +define float @minnum_x_minnum_x_y(float %x, float %y) #0 { + %a = call float @llvm.minnum.f32(float %x, float %y) #0 + %b = call float @llvm.minnum.f32(float %x, float %a) #0 + ret float %b +} + +; CHECK-LABEL: @minnum_y_minnum_x_y +; CHECK-NEXT: call float @llvm.minnum.f32(float %x, float %y) +; CHECK-NEXT: ret float +define float @minnum_y_minnum_x_y(float %x, float %y) #0 { + %a = call float @llvm.minnum.f32(float %x, float %y) #0 + %b = call float @llvm.minnum.f32(float %y, float %a) #0 + ret float %b +} + +; CHECK-LABEL: @minnum_z_minnum_x_y +; CHECK-NEXT: call float @llvm.minnum.f32(float %x, float %y) +; CHECK-NEXT: call float @llvm.minnum.f32(float %z, float %a) +; CHECK-NEXT: ret float +define float @minnum_z_minnum_x_y(float %x, float %y, float %z) #0 { + %a = call float @llvm.minnum.f32(float %x, float %y) #0 + %b = call float @llvm.minnum.f32(float %z, float %a) #0 + ret float %b +} + +; CHECK-LABEL: @minnum_minnum_x_y_z +; CHECK-NEXT: call float @llvm.minnum.f32(float %x, float %y) +; CHECK-NEXT: call float @llvm.minnum.f32(float %a, float %z) +; CHECK-NEXT: ret float +define float @minnum_minnum_x_y_z(float %x, float %y, float %z) #0 { + %a = call float @llvm.minnum.f32(float %x, float %y) #0 + %b = call float @llvm.minnum.f32(float %a, float %z) #0 + ret float %b +} + +; CHECK-LABEL: @minnum4 +; CHECK-NEXT: call float @llvm.minnum.f32(float %x, float %y) +; CHECK-NEXT: call float @llvm.minnum.f32(float %z, float %w) +; CHECK-NEXT: call float @llvm.minnum.f32(float %a, float %b) +; CHECK-NEXT: ret float +define float @minnum4(float %x, float %y, float %z, float %w) #0 { + %a = call float @llvm.minnum.f32(float %x, float %y) #0 + %b = call float @llvm.minnum.f32(float %z, float %w) #0 + %c = call float @llvm.minnum.f32(float %a, float %b) #0 + ret float %c +} + +; CHECK-LABEL: @minnum_x_maxnum_x_y +; CHECK-NEXT: call float @llvm.maxnum.f32 +; CHECK-NEXT: call float @llvm.minnum.f32 +; CHECK-NEXT: ret float +define float @minnum_x_maxnum_x_y(float %x, float %y) #0 { + %a = call float @llvm.maxnum.f32(float %x, float %y) #0 + %b = call float @llvm.minnum.f32(float %x, float %a) #0 + ret float %b +} + +; CHECK-LABEL: @maxnum_x_minnum_x_y +; CHECK-NEXT: call float @llvm.minnum.f32 +; CHECK-NEXT: call float @llvm.maxnum.f32 +; CHECK-NEXT: ret float +define float @maxnum_x_minnum_x_y(float %x, float %y) #0 { + %a = call float @llvm.minnum.f32(float %x, float %y) #0 + %b = call float @llvm.maxnum.f32(float %x, float %a) #0 + ret float %b +} + +; CHECK-LABEL: @fold_minnum_f32_inf_val +; CHECK-NEXT: call float @llvm.minnum.f32(float %x, float 0x7FF0000000000000) +; CHECK-NEXT: ret float +define float @fold_minnum_f32_inf_val(float %x) nounwind { + %val = call float @llvm.minnum.f32(float 0x7FF0000000000000, float %x) #0 + ret float %val +} + +; CHECK-LABEL: @fold_minnum_f32_minf_val +; CHECK-NEXT: ret float 0xFFF0000000000000 +define float @fold_minnum_f32_minf_val(float %x) nounwind { + %val = call float @llvm.minnum.f32(float 0xFFF0000000000000, float %x) #0 + ret float %val +} + +attributes #0 = { nounwind readnone } diff --git a/test/Transforms/InstCombine/mul.ll b/test/Transforms/InstCombine/mul.ll index d19bedc7a10c..4d1e6c700bda 100644 --- a/test/Transforms/InstCombine/mul.ll +++ b/test/Transforms/InstCombine/mul.ll @@ -197,3 +197,94 @@ define <2 x i1> @test21(<2 x i1> %A, <2 x i1> %B) { ret <2 x i1> %C ; CHECK: %C = and <2 x i1> %A, %B } + +define i32 @test22(i32 %A) { +; CHECK-LABEL: @test22( + %B = mul nsw i32 %A, -1 + ret i32 %B +; CHECK: sub nsw i32 0, %A +} + +define i32 @test23(i32 %A) { +; CHECK-LABEL: @test23( + %B = shl nuw i32 %A, 1 + %C = mul nuw i32 %B, 3 + ret i32 %C +; CHECK: mul nuw i32 %A, 6 +} + +define i32 @test24(i32 %A) { +; CHECK-LABEL: @test24( + %B = shl nsw i32 %A, 1 + %C = mul nsw i32 %B, 3 + ret i32 %C +; CHECK: mul nsw i32 %A, 6 +} + +define i32 @test25(i32 %A, i32 %B) { +; CHECK-LABEL: @test25( + %C = sub nsw i32 0, %A + %D = sub nsw i32 0, %B + %E = mul nsw i32 %C, %D + ret i32 %E +; CHECK: mul nsw i32 %A, %B +} + +define i32 @test26(i32 %A, i32 %B) { +; CHECK-LABEL: @test26( + %C = shl nsw i32 1, %B + %D = mul nsw i32 %A, %C + ret i32 %D +; CHECK: shl nsw i32 %A, %B +} + +define i32 @test27(i32 %A, i32 %B) { +; CHECK-LABEL: @test27( + %C = shl i32 1, %B + %D = mul nuw i32 %A, %C + ret i32 %D +; CHECK: shl nuw i32 %A, %B +} + +define i32 @test28(i32 %A) { +; CHECK-LABEL: @test28( + %B = shl i32 1, %A + %C = mul nsw i32 %B, %B + ret i32 %C +; CHECK: %[[shl1:.*]] = shl i32 1, %A +; CHECK-NEXT: %[[shl2:.*]] = shl i32 %[[shl1]], %A +; CHECK-NEXT: ret i32 %[[shl2]] +} + +define i64 @test29(i31 %A, i31 %B) { +; CHECK-LABEL: @test29( + %C = sext i31 %A to i64 + %D = sext i31 %B to i64 + %E = mul i64 %C, %D + ret i64 %E +; CHECK: %[[sext1:.*]] = sext i31 %A to i64 +; CHECK-NEXT: %[[sext2:.*]] = sext i31 %B to i64 +; CHECK-NEXT: %[[mul:.*]] = mul nsw i64 %[[sext1]], %[[sext2]] +; CHECK-NEXT: ret i64 %[[mul]] +} + +define i64 @test30(i32 %A, i32 %B) { +; CHECK-LABEL: @test30( + %C = zext i32 %A to i64 + %D = zext i32 %B to i64 + %E = mul i64 %C, %D + ret i64 %E +; CHECK: %[[zext1:.*]] = zext i32 %A to i64 +; CHECK-NEXT: %[[zext2:.*]] = zext i32 %B to i64 +; CHECK-NEXT: %[[mul:.*]] = mul nuw i64 %[[zext1]], %[[zext2]] +; CHECK-NEXT: ret i64 %[[mul]] +} + +@PR22087 = external global i32 +define i32 @test31(i32 %V) { +; CHECK-LABEL: @test31 + %mul = mul i32 %V, shl (i32 1, i32 zext (i1 icmp ne (i32* inttoptr (i64 1 to i32*), i32* @PR22087) to i32)) + ret i32 %mul +; CHECK: %[[mul:.*]] = shl i32 %V, zext (i1 icmp ne (i32* inttoptr (i64 1 to i32*), i32* @PR22087) to i32) +; CHECK-NEXT: ret i32 %[[mul]] +} diff --git a/test/Transforms/InstCombine/narrow-switch.ll b/test/Transforms/InstCombine/narrow-switch.ll new file mode 100644 index 000000000000..f3f19bae03dd --- /dev/null +++ b/test/Transforms/InstCombine/narrow-switch.ll @@ -0,0 +1,123 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" + +; CHECK-LABEL: define i32 @positive1 +; CHECK: switch i32 +; CHECK: i32 10, label +; CHECK: i32 100, label +; CHECK: i32 1001, label + +define i32 @positive1(i64 %a) { +entry: + %and = and i64 %a, 4294967295 + switch i64 %and, label %sw.default [ + i64 10, label %return + i64 100, label %sw.bb1 + i64 1001, label %sw.bb2 + ] + +sw.bb1: + br label %return + +sw.bb2: + br label %return + +sw.default: + br label %return + +return: + %retval.0 = phi i32 [ 24, %sw.default ], [ 123, %sw.bb2 ], [ 213, %sw.bb1 ], [ 231, %entry ] + ret i32 %retval.0 +} + +; CHECK-LABEL: define i32 @negative1 +; CHECK: switch i32 +; CHECK: i32 -10, label +; CHECK: i32 -100, label +; CHECK: i32 -1001, label + +define i32 @negative1(i64 %a) { +entry: + %or = or i64 %a, -4294967296 + switch i64 %or, label %sw.default [ + i64 -10, label %return + i64 -100, label %sw.bb1 + i64 -1001, label %sw.bb2 + ] + +sw.bb1: + br label %return + +sw.bb2: + br label %return + +sw.default: + br label %return + +return: + %retval.0 = phi i32 [ 24, %sw.default ], [ 123, %sw.bb2 ], [ 213, %sw.bb1 ], [ 231, %entry ] + ret i32 %retval.0 +} + +; Make sure truncating a constant int larger than 64-bit doesn't trigger an +; assertion. + +; CHECK-LABEL: define i32 @trunc72to68 +; CHECK: switch i68 +; CHECK: i68 10, label +; CHECK: i68 100, label +; CHECK: i68 1001, label + +define i32 @trunc72to68(i72 %a) { +entry: + %and = and i72 %a, 295147905179352825855 + switch i72 %and, label %sw.default [ + i72 10, label %return + i72 100, label %sw.bb1 + i72 1001, label %sw.bb2 + ] + +sw.bb1: + br label %return + +sw.bb2: + br label %return + +sw.default: + br label %return + +return: + %retval.0 = phi i32 [ 24, %sw.default ], [ 123, %sw.bb2 ], [ 213, %sw.bb1 ], [ 231, %entry ] + ret i32 %retval.0 +} + +; Make sure to avoid assertion crashes and use the type before +; truncation to generate the sub constant expressions that leads +; to the recomputed condition. +; +; CHECK-LABEL: @trunc64to59 +; CHECK: switch i59 +; CHECK: i59 0, label +; CHECK: i59 18717182647723699, label + +define void @trunc64to59(i64 %a) { +entry: + %tmp0 = and i64 %a, 15 + %tmp1 = mul i64 %tmp0, -6425668444178048401 + %tmp2 = add i64 %tmp1, 5170979678563097242 + %tmp3 = mul i64 %tmp2, 1627972535142754813 + switch i64 %tmp3, label %sw.default [ + i64 847514119312061490, label %sw.bb1 + i64 866231301959785189, label %sw.bb2 + ] + +sw.bb1: + br label %sw.default + +sw.bb2: + br label %sw.default + +sw.default: + ret void +} diff --git a/test/Transforms/InstCombine/no_cgscc_assert.ll b/test/Transforms/InstCombine/no_cgscc_assert.ll new file mode 100644 index 000000000000..cec5297695b1 --- /dev/null +++ b/test/Transforms/InstCombine/no_cgscc_assert.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -inline -instcombine -S | FileCheck %s + +; PR21403: http://llvm.org/bugs/show_bug.cgi?id=21403 +; When the call to sqrtf is replaced by an intrinsic call to fabs, +; it should not cause a problem in CGSCC. + +define float @bar(float %f) #0 { + %mul = fmul fast float %f, %f + %call1 = call float @sqrtf(float %mul) #0 + ret float %call1 + +; CHECK-LABEL: @bar( +; CHECK-NEXT: call float @llvm.fabs.f32 +; CHECK-NEXT: ret float +} + +declare float @sqrtf(float) #0 + +attributes #0 = { readnone "unsafe-fp-math"="true" } diff --git a/test/Transforms/InstCombine/not-fcmp.ll b/test/Transforms/InstCombine/not-fcmp.ll index ad01a6bdf1bc..9718e0b905fc 100644 --- a/test/Transforms/InstCombine/not-fcmp.ll +++ b/test/Transforms/InstCombine/not-fcmp.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -instcombine -S | grep "fcmp uge" +; RUN: opt < %s -instcombine -S | FileCheck %s ; PR1570 define i1 @f(float %X, float %Y) { @@ -6,5 +6,8 @@ entry: %tmp3 = fcmp olt float %X, %Y ; <i1> [#uses=1] %toBoolnot5 = xor i1 %tmp3, true ; <i1> [#uses=1] ret i1 %toBoolnot5 +; CHECK-LABEL: @f( +; CHECK-NEXT: entry: +; CHECK-NEXT: %toBoolnot5 = fcmp uge float %X, %Y +; CHECK-NEXT: ret i1 %toBoolnot5 } - diff --git a/test/Transforms/InstCombine/not.ll b/test/Transforms/InstCombine/not.ll index 4a8825b15c4e..4012ce1ea4ba 100644 --- a/test/Transforms/InstCombine/not.ll +++ b/test/Transforms/InstCombine/not.ll @@ -1,7 +1,8 @@ ; This test makes sure that these instructions are properly eliminated. ; -; RUN: opt < %s -instcombine -S | not grep xor +; RUN: opt < %s -instcombine -S | FileCheck %s +; CHECK-NOT: xor define i32 @test1(i32 %A) { %B = xor i32 %A, -1 ; <i32> [#uses=1] @@ -51,4 +52,3 @@ entry: %retval67 = zext i1 %tmp3 to i8 ; <i8> [#uses=1] ret i8 %retval67 } - diff --git a/test/Transforms/InstCombine/objsize-address-space.ll b/test/Transforms/InstCombine/objsize-address-space.ll index 9cb688423960..a971c913bd41 100644 --- a/test/Transforms/InstCombine/objsize-address-space.ll +++ b/test/Transforms/InstCombine/objsize-address-space.ll @@ -32,7 +32,7 @@ define i16 @foo_as3_i16() nounwind { ret i16 %1 } -@a_alias = alias weak [60 x i8] addrspace(3)* @a_as3 +@a_alias = weak alias [60 x i8] addrspace(3)* @a_as3 define i32 @foo_alias() nounwind { %1 = call i32 @llvm.objectsize.i32.p3i8(i8 addrspace(3)* getelementptr inbounds ([60 x i8] addrspace(3)* @a_alias, i32 0, i32 0), i1 false) ret i32 %1 diff --git a/test/Transforms/InstCombine/objsize.ll b/test/Transforms/InstCombine/objsize.ll index 645903299c86..1285b1c3aa6a 100644 --- a/test/Transforms/InstCombine/objsize.ll +++ b/test/Transforms/InstCombine/objsize.ll @@ -256,7 +256,7 @@ return: ret i32 7 } -@globalalias = alias internal [60 x i8]* @a +@globalalias = internal alias [60 x i8]* @a ; CHECK-LABEL: @test18( ; CHECK-NEXT: ret i32 60 @@ -266,7 +266,7 @@ define i32 @test18() { ret i32 %1 } -@globalalias2 = alias weak [60 x i8]* @a +@globalalias2 = weak alias [60 x i8]* @a ; CHECK-LABEL: @test19( ; CHECK: llvm.objectsize diff --git a/test/Transforms/InstCombine/or-xor.ll b/test/Transforms/InstCombine/or-xor.ll index cec36f119a9a..546b777b4e6b 100644 --- a/test/Transforms/InstCombine/or-xor.ll +++ b/test/Transforms/InstCombine/or-xor.ll @@ -92,3 +92,86 @@ define i32 @test9(i32 %x, i32 %y) nounwind { ; CHECK-NEXT: %z = or i32 %y.not, %x ; CHECK-NEXT: ret i32 %z } + +define i32 @test10(i32 %A, i32 %B) { + %xor1 = xor i32 %B, %A + %not = xor i32 %A, -1 + %xor2 = xor i32 %not, %B + %or = or i32 %xor1, %xor2 + ret i32 %or +; CHECK-LABEL: @test10( +; CHECK-NEXT: ret i32 -1 +} + +; (x | y) & ((~x) ^ y) -> (x & y) +define i32 @test11(i32 %x, i32 %y) { + %or = or i32 %x, %y + %neg = xor i32 %x, -1 + %xor = xor i32 %neg, %y + %and = and i32 %or, %xor + ret i32 %and +; CHECK-LABEL: @test11( +; CHECK-NEXT: %and = and i32 %x, %y +; CHECK-NEXT: ret i32 %and +} + +; ((~x) ^ y) & (x | y) -> (x & y) +define i32 @test12(i32 %x, i32 %y) { + %neg = xor i32 %x, -1 + %xor = xor i32 %neg, %y + %or = or i32 %x, %y + %and = and i32 %xor, %or + ret i32 %and +; CHECK-LABEL: @test12( +; CHECK-NEXT: %and = and i32 %x, %y +; CHECK-NEXT: ret i32 %and +} + +; ((x | y) ^ (x ^ y)) -> (x & y) +define i32 @test13(i32 %x, i32 %y) { + %1 = xor i32 %y, %x + %2 = or i32 %y, %x + %3 = xor i32 %2, %1 + ret i32 %3 +; CHECK-LABEL: @test13( +; CHECK-NEXT: %1 = and i32 %y, %x +; CHECK-NEXT: ret i32 %1 +} + +; ((x | ~y) ^ (~x | y)) -> x ^ y +define i32 @test14(i32 %x, i32 %y) { + %noty = xor i32 %y, -1 + %notx = xor i32 %x, -1 + %or1 = or i32 %x, %noty + %or2 = or i32 %notx, %y + %xor = xor i32 %or1, %or2 + ret i32 %xor +; CHECK-LABEL: @test14( +; CHECK-NEXT: %xor = xor i32 %x, %y +; CHECK-NEXT: ret i32 %xor +} + +; ((x & ~y) ^ (~x & y)) -> x ^ y +define i32 @test15(i32 %x, i32 %y) { + %noty = xor i32 %y, -1 + %notx = xor i32 %x, -1 + %and1 = and i32 %x, %noty + %and2 = and i32 %notx, %y + %xor = xor i32 %and1, %and2 + ret i32 %xor +; CHECK-LABEL: @test15( +; CHECK-NEXT: %xor = xor i32 %x, %y +; CHECK-NEXT: ret i32 %xor +} + +define i32 @test16(i32 %a, i32 %b) { + %or = xor i32 %a, %b + %and1 = and i32 %or, 1 + %and2 = and i32 %b, -2 + %xor = or i32 %and1, %and2 + ret i32 %xor +; CHECK-LABEL: @test16( +; CHECK-NEXT: %1 = and i32 %a, 1 +; CHECK-NEXT: %xor = xor i32 %1, %b +; CHECK-NEXT: ret i32 %xor +} diff --git a/test/Transforms/InstCombine/or.ll b/test/Transforms/InstCombine/or.ll index 1cd897ee90c6..f604bafcc330 100644 --- a/test/Transforms/InstCombine/or.ll +++ b/test/Transforms/InstCombine/or.ll @@ -408,3 +408,111 @@ define i32 @test38(i32* %xp, i32 %y) { %or = or i32 %x, %sext ret i32 %or } + +define i32 @test39(i32 %a, i32 %b) { +; CHECK-LABEL: test39( +; CHECK-NEXT: %or = or i32 %a, %b + %xor = xor i32 %a, -1 + %and = and i32 %xor, %b + %or = or i32 %and, %a + ret i32 %or +} + +define i32 @test40(i32 %a, i32 %b) { +; CHECK-LABEL: test40( +; CHECK-NEXT: %1 = xor i32 %a, -1 +; CHECK-NEXT: %or = or i32 %1, %b + %and = and i32 %a, %b + %xor = xor i32 %a, -1 + %or = or i32 %and, %xor + ret i32 %or +} + +define i32 @test41(i32 %a, i32 %b) { +; CHECK-LABEL: test41( +; CHECK-NEXT: %1 = xor i32 %a, -1 +; CHECK-NEXT: %or = xor i32 %1, %b + %and = and i32 %a, %b + %nega = xor i32 %a, -1 + %xor = xor i32 %nega, %b + %or = or i32 %and, %xor + ret i32 %or +} + +define i32 @test42(i32 %a, i32 %b) { +; CHECK-LABEL: test42( +; CHECK-NEXT: %1 = xor i32 %a, -1 +; CHECK-NEXT: %or = xor i32 %1, %b + %nega = xor i32 %a, -1 + %xor = xor i32 %nega, %b + %and = and i32 %a, %b + %or = or i32 %xor, %and + ret i32 %or +} + +define i32 @test43(i32 %a, i32 %b) { +; CHECK-LABEL: test43( +; CHECK-NEXT: %or = xor i32 %a, %b + %neg = xor i32 %b, -1 + %and = and i32 %a, %neg + %xor = xor i32 %a, %b + %or = or i32 %and, %xor + ret i32 %or +} + +define i32 @test44(i32 %a, i32 %b) { +; CHECK-LABEL: test44( +; CHECK-NEXT: %or = xor i32 %a, %b + %xor = xor i32 %a, %b + %neg = xor i32 %b, -1 + %and = and i32 %a, %neg + %or = or i32 %xor, %and + ret i32 %or +} + +define i32 @test45(i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: test45( +; CHECK-NEXT: %1 = and i32 %x, %z +; CHECK-NEXT: %or1 = or i32 %1, %y +; CHECK-NEXT: ret i32 %or1 + %or = or i32 %y, %z + %and = and i32 %x, %or + %or1 = or i32 %and, %y + ret i32 %or1 +} + +define i1 @test46(i8 signext %c) { + %c.off = add i8 %c, -97 + %cmp1 = icmp ult i8 %c.off, 26 + %c.off17 = add i8 %c, -65 + %cmp2 = icmp ult i8 %c.off17, 26 + %or = or i1 %cmp1, %cmp2 + ret i1 %or +; CHECK-LABEL: @test46( +; CHECK-NEXT: and i8 %c, -33 +; CHECK-NEXT: add i8 %1, -65 +; CHECK-NEXT: icmp ult i8 %2, 26 +} + +define i1 @test47(i8 signext %c) { + %c.off = add i8 %c, -65 + %cmp1 = icmp ule i8 %c.off, 26 + %c.off17 = add i8 %c, -97 + %cmp2 = icmp ule i8 %c.off17, 26 + %or = or i1 %cmp1, %cmp2 + ret i1 %or +; CHECK-LABEL: @test47( +; CHECK-NEXT: and i8 %c, -33 +; CHECK-NEXT: add i8 %1, -65 +; CHECK-NEXT: icmp ult i8 %2, 27 +} + +define i1 @test48(i64 %x, i1 %b) { + %1 = icmp ult i64 %x, 2305843009213693952 + %2 = icmp ugt i64 %x, 2305843009213693951 + %.b = or i1 %2, %b + %3 = or i1 %1, %.b + ret i1 %3 +; CHECK-LABEL: @test48( +; CHECK-NEXT: ret i1 true +} diff --git a/test/Transforms/InstCombine/overflow-mul.ll b/test/Transforms/InstCombine/overflow-mul.ll index cbb2f5f95003..6d8d40bcac3e 100644 --- a/test/Transforms/InstCombine/overflow-mul.ll +++ b/test/Transforms/InstCombine/overflow-mul.ll @@ -173,3 +173,16 @@ define <4 x i32> @pr20113(<4 x i16> %a, <4 x i16> %b) { %vcgez.i = sext <4 x i1> %tmp to <4 x i32> ret <4 x i32> %vcgez.i } + +@pr21445_data = external global i32 +define i1 @pr21445(i8 %a) { +; CHECK-LABEL: @pr21445( +; CHECK-NEXT: %[[umul:.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 ptrtoint (i32* @pr21445_data to i8)) +; CHECK-NEXT: %[[cmp:.*]] = extractvalue { i8, i1 } %[[umul]], 1 +; CHECK-NEXT: ret i1 %[[cmp]] + %ext = zext i8 %a to i32 + %mul = mul i32 %ext, zext (i8 ptrtoint (i32* @pr21445_data to i8) to i32) + %and = and i32 %mul, 255 + %cmp = icmp ne i32 %mul, %and + ret i1 %cmp +} diff --git a/test/Transforms/InstCombine/pr12251.ll b/test/Transforms/InstCombine/pr12251.ll index 74a41eb7d227..8c382bb104ac 100644 --- a/test/Transforms/InstCombine/pr12251.ll +++ b/test/Transforms/InstCombine/pr12251.ll @@ -12,4 +12,4 @@ entry: ; CHECK-NEXT: %tobool = icmp ne i8 %a, 0 ; CHECK-NEXT: ret i1 %tobool -!0 = metadata !{i8 0, i8 2} +!0 = !{i8 0, i8 2} diff --git a/test/Transforms/InstCombine/pr12338.ll b/test/Transforms/InstCombine/pr12338.ll index d34600f0fa58..7e0bf59614c3 100644 --- a/test/Transforms/InstCombine/pr12338.ll +++ b/test/Transforms/InstCombine/pr12338.ll @@ -4,9 +4,9 @@ define void @entry() nounwind { entry: br label %for.cond +; CHECK: br label %for.cond for.cond: %local = phi <1 x i32> [ <i32 0>, %entry ], [ %phi2, %cond.end47 ] -; CHECK: sub <1 x i32> <i32 92>, %local %phi3 = sub <1 x i32> zeroinitializer, %local br label %cond.end diff --git a/test/Transforms/InstCombine/pr21199.ll b/test/Transforms/InstCombine/pr21199.ll new file mode 100644 index 000000000000..e6599fb640d7 --- /dev/null +++ b/test/Transforms/InstCombine/pr21199.ll @@ -0,0 +1,25 @@ +; do not replace a 'select' with 'or' in 'select - cmp - br' sequence +; RUN: opt -instcombine -S < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @f(i32) + +define void @test(i32 %len) { +entry: + %cmp = icmp ult i32 %len, 8 + %cond = select i1 %cmp, i32 %len, i32 8 + %cmp11 = icmp ult i32 0, %cond + br i1 %cmp11, label %for.body, label %for.end + +for.body: ; preds = %entry, %for.body + %i.02 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + tail call void @f(i32 %cond) + %inc = add i32 %i.02, 1 + %cmp1 = icmp ult i32 %inc, %cond + br i1 %cmp1, label %for.body, label %for.end + +for.end: ; preds = %for.body, %entry + ret void +; CHECK: select +} diff --git a/test/Transforms/InstCombine/pr21210.ll b/test/Transforms/InstCombine/pr21210.ll new file mode 100644 index 000000000000..1db87949dda0 --- /dev/null +++ b/test/Transforms/InstCombine/pr21210.ll @@ -0,0 +1,50 @@ +; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -instcombine -S | FileCheck %s +; Checks that the select-icmp optimization is safe in two cases +declare void @foo(i32) +declare i32 @bar(i32) + +; don't replace 'cond' by 'len' in the home block ('bb') that +; contains the select +define void @test1(i32 %len) { +entry: + br label %bb + +bb: + %cmp = icmp ult i32 %len, 8 + %cond = select i1 %cmp, i32 %len, i32 8 + call void @foo(i32 %cond) + %cmp11 = icmp eq i32 %cond, 8 + br i1 %cmp11, label %for.end, label %bb + +for.end: + ret void +; CHECK: select +; CHECK: icmp eq i32 %cond, 8 +} + +; don't replace 'cond' by 'len' in a block ('b1') that dominates all uses +; of the select outside the home block ('bb'), but can be reached from the home +; block on another path ('bb -> b0 -> b1') +define void @test2(i32 %len) { +entry: + %0 = call i32 @bar(i32 %len); + %cmp = icmp ult i32 %len, 4 + br i1 %cmp, label %bb, label %b1 +bb: + %cond = select i1 %cmp, i32 %len, i32 8 + %cmp11 = icmp eq i32 %cond, 8 + br i1 %cmp11, label %b0, label %b1 + +b0: + call void @foo(i32 %len) + br label %b1 + +b1: +; CHECK: phi i32 [ %cond, %bb ], [ undef, %b0 ], [ %0, %entry ] + %1 = phi i32 [ %cond, %bb ], [ undef, %b0 ], [ %0, %entry ] + br label %ret + +ret: + call void @foo(i32 %1) + ret void +} diff --git a/test/Transforms/InstCombine/pr21651.ll b/test/Transforms/InstCombine/pr21651.ll new file mode 100644 index 000000000000..914785f329af --- /dev/null +++ b/test/Transforms/InstCombine/pr21651.ll @@ -0,0 +1,20 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define void @PR21651() { + switch i2 0, label %out [ + i2 0, label %out + i2 1, label %out + ] + +out: + ret void +} + +; CHECK-LABEL: define void @PR21651( +; CHECK: switch i2 0, label %out [ +; CHECK: i2 0, label %out +; CHECK: i2 1, label %out +; CHECK: ] +; CHECK: out: ; preds = %0, %0, %0 +; CHECK: ret void +; CHECK: } diff --git a/test/Transforms/InstCombine/pr21891.ll b/test/Transforms/InstCombine/pr21891.ll new file mode 100644 index 000000000000..8194976b6233 --- /dev/null +++ b/test/Transforms/InstCombine/pr21891.ll @@ -0,0 +1,18 @@ +; RUN: opt %s -instcombine + +define i32 @f(i32 %theNumber) { +entry: + %cmp = icmp sgt i32 %theNumber, -1 + call void @llvm.assume(i1 %cmp) + br i1 true, label %if.then, label %if.end + +if.then: ; preds = %entry + %shl = shl nuw i32 %theNumber, 1 + br label %if.end + +if.end: ; preds = %if.then, %entry + %phi = phi i32 [ %shl, %if.then ], [ undef, %entry ] + ret i32 %phi +} + +declare void @llvm.assume(i1) diff --git a/test/Transforms/InstCombine/range-check.ll b/test/Transforms/InstCombine/range-check.ll new file mode 100644 index 000000000000..35f11dd39ef3 --- /dev/null +++ b/test/Transforms/InstCombine/range-check.ll @@ -0,0 +1,159 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; Check simplification of +; (icmp sgt x, -1) & (icmp sgt/sge n, x) --> icmp ugt/uge n, x + +; CHECK-LABEL: define i1 @test_and1 +; CHECK: [[R:%[0-9]+]] = icmp ugt i32 %nn, %x +; CHECK: ret i1 [[R]] +define i1 @test_and1(i32 %x, i32 %n) { + %nn = and i32 %n, 2147483647 + %a = icmp sge i32 %x, 0 + %b = icmp slt i32 %x, %nn + %c = and i1 %a, %b + ret i1 %c +} + +; CHECK-LABEL: define i1 @test_and2 +; CHECK: [[R:%[0-9]+]] = icmp uge i32 %nn, %x +; CHECK: ret i1 [[R]] +define i1 @test_and2(i32 %x, i32 %n) { + %nn = and i32 %n, 2147483647 + %a = icmp sgt i32 %x, -1 + %b = icmp sle i32 %x, %nn + %c = and i1 %a, %b + ret i1 %c +} + +; CHECK-LABEL: define i1 @test_and3 +; CHECK: [[R:%[0-9]+]] = icmp ugt i32 %nn, %x +; CHECK: ret i1 [[R]] +define i1 @test_and3(i32 %x, i32 %n) { + %nn = and i32 %n, 2147483647 + %a = icmp sgt i32 %nn, %x + %b = icmp sge i32 %x, 0 + %c = and i1 %a, %b + ret i1 %c +} + +; CHECK-LABEL: define i1 @test_and4 +; CHECK: [[R:%[0-9]+]] = icmp uge i32 %nn, %x +; CHECK: ret i1 [[R]] +define i1 @test_and4(i32 %x, i32 %n) { + %nn = and i32 %n, 2147483647 + %a = icmp sge i32 %nn, %x + %b = icmp sge i32 %x, 0 + %c = and i1 %a, %b + ret i1 %c +} + +; CHECK-LABEL: define i1 @test_or1 +; CHECK: [[R:%[0-9]+]] = icmp ule i32 %nn, %x +; CHECK: ret i1 [[R]] +define i1 @test_or1(i32 %x, i32 %n) { + %nn = and i32 %n, 2147483647 + %a = icmp slt i32 %x, 0 + %b = icmp sge i32 %x, %nn + %c = or i1 %a, %b + ret i1 %c +} + +; CHECK-LABEL: define i1 @test_or2 +; CHECK: [[R:%[0-9]+]] = icmp ult i32 %nn, %x +; CHECK: ret i1 [[R]] +define i1 @test_or2(i32 %x, i32 %n) { + %nn = and i32 %n, 2147483647 + %a = icmp sle i32 %x, -1 + %b = icmp sgt i32 %x, %nn + %c = or i1 %a, %b + ret i1 %c +} + +; CHECK-LABEL: define i1 @test_or3 +; CHECK: [[R:%[0-9]+]] = icmp ule i32 %nn, %x +; CHECK: ret i1 [[R]] +define i1 @test_or3(i32 %x, i32 %n) { + %nn = and i32 %n, 2147483647 + %a = icmp sle i32 %nn, %x + %b = icmp slt i32 %x, 0 + %c = or i1 %a, %b + ret i1 %c +} + +; CHECK-LABEL: define i1 @test_or4 +; CHECK: [[R:%[0-9]+]] = icmp ult i32 %nn, %x +; CHECK: ret i1 [[R]] +define i1 @test_or4(i32 %x, i32 %n) { + %nn = and i32 %n, 2147483647 + %a = icmp slt i32 %nn, %x + %b = icmp slt i32 %x, 0 + %c = or i1 %a, %b + ret i1 %c +} + +; Negative tests + +; CHECK-LABEL: define i1 @negative1 +; CHECK: %a = icmp +; CHECK: %b = icmp +; CHECK: %c = and i1 %a, %b +; CHECK: ret i1 %c +define i1 @negative1(i32 %x, i32 %n) { + %nn = and i32 %n, 2147483647 + %a = icmp slt i32 %x, %nn + %b = icmp sgt i32 %x, 0 ; should be: icmp sge + %c = and i1 %a, %b + ret i1 %c +} + +; CHECK-LABEL: define i1 @negative2 +; CHECK: %a = icmp +; CHECK: %b = icmp +; CHECK: %c = and i1 %a, %b +; CHECK: ret i1 %c +define i1 @negative2(i32 %x, i32 %n) { + %a = icmp slt i32 %x, %n ; n can be negative + %b = icmp sge i32 %x, 0 + %c = and i1 %a, %b + ret i1 %c +} + +; CHECK-LABEL: define i1 @negative3 +; CHECK: %a = icmp +; CHECK: %b = icmp +; CHECK: %c = and i1 %a, %b +; CHECK: ret i1 %c +define i1 @negative3(i32 %x, i32 %y, i32 %n) { + %nn = and i32 %n, 2147483647 + %a = icmp slt i32 %x, %nn + %b = icmp sge i32 %y, 0 ; should compare %x and not %y + %c = and i1 %a, %b + ret i1 %c +} + +; CHECK-LABEL: define i1 @negative4 +; CHECK: %a = icmp +; CHECK: %b = icmp +; CHECK: %c = and i1 %a, %b +; CHECK: ret i1 %c +define i1 @negative4(i32 %x, i32 %n) { + %nn = and i32 %n, 2147483647 + %a = icmp ne i32 %x, %nn ; should be: icmp slt/sle + %b = icmp sge i32 %x, 0 + %c = and i1 %a, %b + ret i1 %c +} + +; CHECK-LABEL: define i1 @negative5 +; CHECK: %a = icmp +; CHECK: %b = icmp +; CHECK: %c = or i1 %a, %b +; CHECK: ret i1 %c +define i1 @negative5(i32 %x, i32 %n) { + %nn = and i32 %n, 2147483647 + %a = icmp slt i32 %x, %nn + %b = icmp sge i32 %x, 0 + %c = or i1 %a, %b ; should be: and + ret i1 %c +} + diff --git a/test/Transforms/InstCombine/select-cmp-br.ll b/test/Transforms/InstCombine/select-cmp-br.ll new file mode 100644 index 000000000000..f10d58783a77 --- /dev/null +++ b/test/Transforms/InstCombine/select-cmp-br.ll @@ -0,0 +1,155 @@ +; Replace a 'select' with 'or' in 'select - cmp [eq|ne] - br' sequence +; RUN: opt -instcombine -S < %s | FileCheck %s + +%C = type <{ %struct.S }> +%struct.S = type { i64*, i32, i32 } + +declare void @bar(%struct.S *) #1 +declare void @foobar() + +define void @test1(%C*) { +entry: + %1 = getelementptr inbounds %C* %0, i64 0, i32 0, i32 0 + %m = load i64** %1, align 8 + %2 = getelementptr inbounds %C* %0, i64 1, i32 0, i32 0 + %n = load i64** %2, align 8 + %3 = getelementptr inbounds i64* %m, i64 9 + %4 = bitcast i64* %3 to i64 (%C*)** + %5 = load i64 (%C*)** %4, align 8 + %6 = icmp eq i64* %m, %n + %7 = select i1 %6, %C* %0, %C* null + %8 = icmp eq %C* %7, null + br i1 %8, label %12, label %10 + +; <label>:9 ; preds = %10, %12 + ret void + +; <label>:10 ; preds = %entry + %11 = getelementptr inbounds %C* %7, i64 0, i32 0 + tail call void @bar(%struct.S* %11) + br label %9 + +; <label>:12 ; preds = %entry + %13 = tail call i64 %5(%C* %0) + br label %9 +; CHECK-LABEL: @test1( +; CHECK-NOT: select +; CHECK: or +; CHECK-NOT: select +} + +define void @test2(%C*) { +entry: + %1 = getelementptr inbounds %C* %0, i64 0, i32 0, i32 0 + %m = load i64** %1, align 8 + %2 = getelementptr inbounds %C* %0, i64 1, i32 0, i32 0 + %n = load i64** %2, align 8 + %3 = getelementptr inbounds i64* %m, i64 9 + %4 = bitcast i64* %3 to i64 (%C*)** + %5 = load i64 (%C*)** %4, align 8 + %6 = icmp eq i64* %m, %n + %7 = select i1 %6, %C* null, %C* %0 + %8 = icmp eq %C* %7, null + br i1 %8, label %12, label %10 + +; <label>:9 ; preds = %10, %12 + ret void + +; <label>:10 ; preds = %entry + %11 = getelementptr inbounds %C* %7, i64 0, i32 0 + tail call void @bar(%struct.S* %11) + br label %9 + +; <label>:12 ; preds = %entry + %13 = tail call i64 %5(%C* %0) + br label %9 +; CHECK-LABEL: @test2( +; CHECK-NOT: select +; CHECK: or +; CHECK-NOT: select +} + +define void @test3(%C*) { +entry: + %1 = getelementptr inbounds %C* %0, i64 0, i32 0, i32 0 + %m = load i64** %1, align 8 + %2 = getelementptr inbounds %C* %0, i64 1, i32 0, i32 0 + %n = load i64** %2, align 8 + %3 = getelementptr inbounds i64* %m, i64 9 + %4 = bitcast i64* %3 to i64 (%C*)** + %5 = load i64 (%C*)** %4, align 8 + %6 = icmp eq i64* %m, %n + %7 = select i1 %6, %C* %0, %C* null + %8 = icmp ne %C* %7, null + br i1 %8, label %10, label %12 + +; <label>:9 ; preds = %10, %12 + ret void + +; <label>:10 ; preds = %entry + %11 = getelementptr inbounds %C* %7, i64 0, i32 0 + tail call void @bar(%struct.S* %11) + br label %9 + +; <label>:12 ; preds = %entry + %13 = tail call i64 %5(%C* %0) + br label %9 +; CHECK-LABEL: @test3( +; CHECK-NOT: select +; CHECK: or +; CHECK-NOT: select +} + +define void @test4(%C*) { +entry: + %1 = getelementptr inbounds %C* %0, i64 0, i32 0, i32 0 + %m = load i64** %1, align 8 + %2 = getelementptr inbounds %C* %0, i64 1, i32 0, i32 0 + %n = load i64** %2, align 8 + %3 = getelementptr inbounds i64* %m, i64 9 + %4 = bitcast i64* %3 to i64 (%C*)** + %5 = load i64 (%C*)** %4, align 8 + %6 = icmp eq i64* %m, %n + %7 = select i1 %6, %C* null, %C* %0 + %8 = icmp ne %C* %7, null + br i1 %8, label %10, label %12 + +; <label>:9 ; preds = %10, %12 + ret void + +; <label>:10 ; preds = %entry + %11 = getelementptr inbounds %C* %7, i64 0, i32 0 + tail call void @bar(%struct.S* %11) + br label %9 + +; <label>:12 ; preds = %entry + %13 = tail call i64 %5(%C* %0) + br label %9 +; CHECK-LABEL: @test4( +; CHECK-NOT: select +; CHECK: or +; CHECK-NOT: select +} + +define void @test5(%C*, i1) { +entry: + %2 = select i1 %1, %C* null, %C* %0 + %3 = icmp ne %C* %2, null + br i1 %3, label %5, label %7 + +; <label>:4 ; preds = %10, %12 + ret void + +; <label>:5 ; preds = %entry + %6 = getelementptr inbounds %C* %2, i64 0, i32 0 + tail call void @bar(%struct.S* %6) + br label %4 + +; <label>:7 ; preds = %entry + tail call void @foobar() + br label %4 +; CHECK-LABEL: @test5( +; CHECK-NOT: select +; CHECK: or +; CHECK-NOT: select +} diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll index d625f3b1b33d..054f00a0de49 100644 --- a/test/Transforms/InstCombine/select.ll +++ b/test/Transforms/InstCombine/select.ll @@ -1,7 +1,8 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s ; This test makes sure that these instructions are properly eliminated. ; PR1822 -; RUN: opt < %s -instcombine -S | FileCheck %s +target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64" define i32 @test1(i32 %A, i32 %B) { %C = select i1 false, i32 %A, i32 %B @@ -307,6 +308,26 @@ define i32 @test16(i1 %C, i32* %P) { ; CHECK: ret i32 %V } +;; It may be legal to load from a null address in a non-zero address space +define i32 @test16_neg(i1 %C, i32 addrspace(1)* %P) { + %P2 = select i1 %C, i32 addrspace(1)* %P, i32 addrspace(1)* null + %V = load i32 addrspace(1)* %P2 + ret i32 %V +; CHECK-LABEL: @test16_neg +; CHECK-NEXT: %P2 = select i1 %C, i32 addrspace(1)* %P, i32 addrspace(1)* null +; CHECK-NEXT: %V = load i32 addrspace(1)* %P2 +; CHECK: ret i32 %V +} +define i32 @test16_neg2(i1 %C, i32 addrspace(1)* %P) { + %P2 = select i1 %C, i32 addrspace(1)* null, i32 addrspace(1)* %P + %V = load i32 addrspace(1)* %P2 + ret i32 %V +; CHECK-LABEL: @test16_neg2 +; CHECK-NEXT: %P2 = select i1 %C, i32 addrspace(1)* null, i32 addrspace(1)* %P +; CHECK-NEXT: %V = load i32 addrspace(1)* %P2 +; CHECK: ret i32 %V +} + define i1 @test17(i32* %X, i1 %C) { %R = select i1 %C, i32* %X, i32* null %RV = icmp eq i32* %R, null @@ -916,9 +937,9 @@ define i32 @select_icmp_eq_and_4096_0_or_4096(i32 %x, i32 %y) { } ; CHECK-LABEL: @select_icmp_eq_0_and_1_or_1( -; CHECK-NEXT: [[AND:%[a-z0-9]+]] = and i64 %x, 1 -; CHECK-NEXT: [[ZEXT:%[a-z0-9]+]] = trunc i64 [[AND]] to i32 -; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 [[XOR]], %y +; CHECK-NEXT: [[TRUNC:%.+]] = trunc i64 %x to i32 +; CHECK-NEXT: [[AND:%.+]] = and i32 [[TRUNC]], 1 +; CHECK-NEXT: [[OR:%.+]] = or i32 [[XOR]], %y ; CHECK-NEXT: ret i32 [[OR]] define i32 @select_icmp_eq_0_and_1_or_1(i64 %x, i32 %y) { %and = and i64 %x, 1 @@ -957,11 +978,11 @@ define i32 @select_icmp_ne_0_and_32_or_4096(i32 %x, i32 %y) { } ; CHECK-LABEL: @select_icmp_ne_0_and_1073741824_or_8( -; CHECK-NEXT: [[LSHR:%[a-z0-9]+]] = lshr i32 %x, 27 -; CHECK-NEXT: [[AND:%[a-z0-9]+]] = and i32 [[LSHR]], 8 -; CHECK-NEXT: [[TRUNC:%[a-z0-9]+]] = trunc i32 [[AND]] to i8 -; CHECK-NEXT: [[XOR:%[a-z0-9]+]] = xor i8 [[TRUNC]], 8 -; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i8 [[XOR]], %y +; CHECK-NEXT: [[LSHR:%.+]] = lshr i32 %x, 27 +; CHECK-NEXT: [[TRUNC:%.+]] = trunc i32 [[LSHR]] to i8 +; CHECK-NEXT: [[AND:%.+]] = and i8 [[TRUNC]], 8 +; CHECK-NEXT: [[XOR:%.+]] = xor i8 [[AND]], 8 +; CHECK-NEXT: [[OR:%.+]] = or i8 [[XOR]], %y ; CHECK-NEXT: ret i8 [[OR]] define i8 @select_icmp_ne_0_and_1073741824_or_8(i32 %x, i8 %y) { %and = and i32 %x, 1073741824 @@ -996,17 +1017,6 @@ define <2 x i32> @select_icmp_eq_and_1_0_or_vector_of_2s(i32 %x, <2 x i32> %y) { ret <2 x i32> %select } -; CHECK-LABEL: @select_icmp_and_8_eq_0_or_8( -; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 %x, 8 -; CHECK-NEXT: ret i32 [[OR]] -define i32 @select_icmp_and_8_eq_0_or_8(i32 %x) { - %and = and i32 %x, 8 - %cmp = icmp eq i32 %and, 0 - %or = or i32 %x, 8 - %or.x = select i1 %cmp, i32 %or, i32 %x - ret i32 %or.x -} - ; CHECK-LABEL: @select_icmp_and_8_ne_0_xor_8( ; CHECK-NEXT: [[AND:%[a-z0-9]+]] = and i32 %x, -9 ; CHECK-NEXT: ret i32 [[AND]] @@ -1029,27 +1039,6 @@ define i32 @select_icmp_and_8_eq_0_xor_8(i32 %x) { ret i32 %xor.x } -; CHECK-LABEL: @select_icmp_and_8_ne_0_and_not_8( -; CHECK-NEXT: [[AND:%[a-z0-9]+]] = and i32 %x, -9 -; CHECK-NEXT: ret i32 [[AND]] -define i32 @select_icmp_and_8_ne_0_and_not_8(i32 %x) { - %and = and i32 %x, 8 - %cmp = icmp eq i32 %and, 0 - %and1 = and i32 %x, -9 - %x.and1 = select i1 %cmp, i32 %x, i32 %and1 - ret i32 %x.and1 -} - -; CHECK-LABEL: @select_icmp_and_8_eq_0_and_not_8( -; CHECK-NEXT: ret i32 %x -define i32 @select_icmp_and_8_eq_0_and_not_8(i32 %x) { - %and = and i32 %x, 8 - %cmp = icmp eq i32 %and, 0 - %and1 = and i32 %x, -9 - %and1.x = select i1 %cmp, i32 %and1, i32 %x - ret i32 %and1.x -} - ; CHECK-LABEL: @select_icmp_x_and_8_eq_0_y_xor_8( ; CHECK: select i1 %cmp, i64 %y, i64 %xor define i64 @select_icmp_x_and_8_eq_0_y_xor_8(i32 %x, i64 %y) { @@ -1060,16 +1049,6 @@ define i64 @select_icmp_x_and_8_eq_0_y_xor_8(i32 %x, i64 %y) { ret i64 %y.xor } -; CHECK-LABEL: @select_icmp_x_and_8_eq_0_y_and_not_8( -; CHECK: select i1 %cmp, i64 %y, i64 %and1 -define i64 @select_icmp_x_and_8_eq_0_y_and_not_8(i32 %x, i64 %y) { - %and = and i32 %x, 8 - %cmp = icmp eq i32 %and, 0 - %and1 = and i64 %y, -9 - %y.and1 = select i1 %cmp, i64 %y, i64 %and1 - ret i64 %y.and1 -} - ; CHECK-LABEL: @select_icmp_x_and_8_ne_0_y_xor_8( ; CHECK: select i1 %cmp, i64 %xor, i64 %y define i64 @select_icmp_x_and_8_ne_0_y_xor_8(i32 %x, i64 %y) { @@ -1080,16 +1059,6 @@ define i64 @select_icmp_x_and_8_ne_0_y_xor_8(i32 %x, i64 %y) { ret i64 %xor.y } -; CHECK-LABEL: @select_icmp_x_and_8_ne_0_y_and_not_8( -; CHECK: select i1 %cmp, i64 %and1, i64 %y -define i64 @select_icmp_x_and_8_ne_0_y_and_not_8(i32 %x, i64 %y) { - %and = and i32 %x, 8 - %cmp = icmp eq i32 %and, 0 - %and1 = and i64 %y, -9 - %and1.y = select i1 %cmp, i64 %and1, i64 %y - ret i64 %and1.y -} - ; CHECK-LABEL: @select_icmp_x_and_8_ne_0_y_or_8( ; CHECK: xor i64 %1, 8 ; CHECK: or i64 %2, %y @@ -1101,6 +1070,39 @@ define i64 @select_icmp_x_and_8_ne_0_y_or_8(i32 %x, i64 %y) { ret i64 %or.y } +; CHECK-LABEL: @select_icmp_and_2147483648_ne_0_xor_2147483648( +; CHECK-NEXT: [[AND:%[a-z0-9]+]] = and i32 %x, 2147483647 +; CHECK-NEXT: ret i32 [[AND]] +define i32 @select_icmp_and_2147483648_ne_0_xor_2147483648(i32 %x) { + %and = and i32 %x, 2147483648 + %cmp = icmp eq i32 %and, 0 + %xor = xor i32 %x, 2147483648 + %x.xor = select i1 %cmp, i32 %x, i32 %xor + ret i32 %x.xor +} + +; CHECK-LABEL: @select_icmp_and_2147483648_eq_0_xor_2147483648( +; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 %x, -2147483648 +; CHECK-NEXT: ret i32 [[OR]] +define i32 @select_icmp_and_2147483648_eq_0_xor_2147483648(i32 %x) { + %and = and i32 %x, 2147483648 + %cmp = icmp eq i32 %and, 0 + %xor = xor i32 %x, 2147483648 + %xor.x = select i1 %cmp, i32 %xor, i32 %x + ret i32 %xor.x +} + +; CHECK-LABEL: @select_icmp_x_and_2147483648_ne_0_or_2147483648( +; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 %x, -2147483648 +; CHECK-NEXT: ret i32 [[OR]] +define i32 @select_icmp_x_and_2147483648_ne_0_or_2147483648(i32 %x) { + %and = and i32 %x, 2147483648 + %cmp = icmp eq i32 %and, 0 + %or = or i32 %x, 2147483648 + %or.x = select i1 %cmp, i32 %or, i32 %x + ret i32 %or.x +} + define i32 @test65(i64 %x) { %1 = and i64 %x, 16 %2 = icmp ne i64 %1, 0 @@ -1108,10 +1110,11 @@ define i32 @test65(i64 %x) { ret i32 %3 ; CHECK-LABEL: @test65( -; CHECK: and i64 %x, 16 -; CHECK: trunc i64 %1 to i32 -; CHECK: lshr exact i32 %2, 3 -; CHECK: xor i32 %3, 42 +; CHECK: %[[TRUNC:.*]] = trunc i64 %x to i32 +; CHECK: %[[LSHR:.*]] = lshr i32 %[[TRUNC]], 3 +; CHECK: %[[AND:.*]] = and i32 %[[LSHR]], 2 +; CHECK: %[[XOR:.*]] = xor i32 %[[AND]], 42 +; CHECK: ret i32 %[[XOR]] } define i32 @test66(i64 %x) { @@ -1236,3 +1239,256 @@ define i32 @test75(i32 %x) { ; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 68, i32 %x ; CHECK-NEXT: ret i32 [[SEL]] } + +@under_aligned = external global i32, align 1 + +define i32 @test76(i1 %flag, i32* %x) { +; The load here must not be speculated around the select. One side of the +; select is trivially dereferencable but may have a lower alignment than the +; load does. +; CHECK-LABEL: @test76( +; CHECK: store i32 0, i32* %x +; CHECK: %[[P:.*]] = select i1 %flag, i32* @under_aligned, i32* %x +; CHECK: load i32* %[[P]] + + store i32 0, i32* %x + %p = select i1 %flag, i32* @under_aligned, i32* %x + %v = load i32* %p + ret i32 %v +} + +declare void @scribble_on_i32(i32*) + +define i32 @test77(i1 %flag, i32* %x) { +; The load here must not be speculated around the select. One side of the +; select is trivially dereferencable but may have a lower alignment than the +; load does. +; CHECK-LABEL: @test77( +; CHECK: %[[A:.*]] = alloca i32, align 1 +; CHECK: call void @scribble_on_i32(i32* %[[A]]) +; CHECK: store i32 0, i32* %x +; CHECK: %[[P:.*]] = select i1 %flag, i32* %[[A]], i32* %x +; CHECK: load i32* %[[P]] + + %under_aligned = alloca i32, align 1 + call void @scribble_on_i32(i32* %under_aligned) + store i32 0, i32* %x + %p = select i1 %flag, i32* %under_aligned, i32* %x + %v = load i32* %p + ret i32 %v +} + +define i32 @test78(i1 %flag, i32* %x, i32* %y, i32* %z) { +; Test that we can speculate the loads around the select even when we can't +; fold the load completely away. +; CHECK-LABEL: @test78( +; CHECK: %[[V1:.*]] = load i32* %x +; CHECK-NEXT: %[[V2:.*]] = load i32* %y +; CHECK-NEXT: %[[S:.*]] = select i1 %flag, i32 %[[V1]], i32 %[[V2]] +; CHECK-NEXT: ret i32 %[[S]] +entry: + store i32 0, i32* %x + store i32 0, i32* %y + ; Block forwarding by storing to %z which could alias either %x or %y. + store i32 42, i32* %z + %p = select i1 %flag, i32* %x, i32* %y + %v = load i32* %p + ret i32 %v +} + +define float @test79(i1 %flag, float* %x, i32* %y, i32* %z) { +; Test that we can speculate the loads around the select even when we can't +; fold the load completely away. +; CHECK-LABEL: @test79( +; CHECK: %[[V1:.*]] = load float* %x +; CHECK-NEXT: %[[V2:.*]] = load float* %y +; CHECK-NEXT: %[[S:.*]] = select i1 %flag, float %[[V1]], float %[[V2]] +; CHECK-NEXT: ret float %[[S]] +entry: + %x1 = bitcast float* %x to i32* + %y1 = bitcast i32* %y to float* + store i32 0, i32* %x1 + store i32 0, i32* %y + ; Block forwarding by storing to %z which could alias either %x or %y. + store i32 42, i32* %z + %p = select i1 %flag, float* %x, float* %y1 + %v = load float* %p + ret float %v +} + +define i32 @test80(i1 %flag) { +; Test that when we speculate the loads around the select they fold throug +; load->load folding and load->store folding. +; CHECK-LABEL: @test80( +; CHECK: %[[X:.*]] = alloca i32 +; CHECK-NEXT: %[[Y:.*]] = alloca i32 +; CHECK: %[[V:.*]] = load i32* %[[X]] +; CHECK-NEXT: store i32 %[[V]], i32* %[[Y]] +; CHECK-NEXT: ret i32 %[[V]] +entry: + %x = alloca i32 + %y = alloca i32 + call void @scribble_on_i32(i32* %x) + call void @scribble_on_i32(i32* %y) + %tmp = load i32* %x + store i32 %tmp, i32* %y + %p = select i1 %flag, i32* %x, i32* %y + %v = load i32* %p + ret i32 %v +} + +define float @test81(i1 %flag) { +; Test that we can speculate the load around the select even though they use +; differently typed pointers. +; CHECK-LABEL: @test81( +; CHECK: %[[X:.*]] = alloca i32 +; CHECK-NEXT: %[[Y:.*]] = alloca i32 +; CHECK: %[[V:.*]] = load i32* %[[X]] +; CHECK-NEXT: store i32 %[[V]], i32* %[[Y]] +; CHECK-NEXT: %[[C:.*]] = bitcast i32 %[[V]] to float +; CHECK-NEXT: ret float %[[C]] +entry: + %x = alloca float + %y = alloca i32 + %x1 = bitcast float* %x to i32* + %y1 = bitcast i32* %y to float* + call void @scribble_on_i32(i32* %x1) + call void @scribble_on_i32(i32* %y) + %tmp = load i32* %x1 + store i32 %tmp, i32* %y + %p = select i1 %flag, float* %x, float* %y1 + %v = load float* %p + ret float %v +} + +define i32 @test82(i1 %flag) { +; Test that we can speculate the load around the select even though they use +; differently typed pointers. +; CHECK-LABEL: @test82( +; CHECK: %[[X:.*]] = alloca float +; CHECK-NEXT: %[[Y:.*]] = alloca i32 +; CHECK-NEXT: %[[X1:.*]] = bitcast float* %[[X]] to i32* +; CHECK-NEXT: %[[Y1:.*]] = bitcast i32* %[[Y]] to float* +; CHECK: %[[V:.*]] = load float* %[[X]] +; CHECK-NEXT: store float %[[V]], float* %[[Y1]] +; CHECK-NEXT: %[[C:.*]] = bitcast float %[[V]] to i32 +; CHECK-NEXT: ret i32 %[[C]] +entry: + %x = alloca float + %y = alloca i32 + %x1 = bitcast float* %x to i32* + %y1 = bitcast i32* %y to float* + call void @scribble_on_i32(i32* %x1) + call void @scribble_on_i32(i32* %y) + %tmp = load float* %x + store float %tmp, float* %y1 + %p = select i1 %flag, i32* %x1, i32* %y + %v = load i32* %p + ret i32 %v +} + +declare void @scribble_on_i64(i64*) +declare void @scribble_on_i128(i128*) + +define i8* @test83(i1 %flag) { +; Test that we can speculate the load around the select even though they use +; differently typed pointers and requires inttoptr casts. +; CHECK-LABEL: @test83( +; CHECK: %[[X:.*]] = alloca i8* +; CHECK-NEXT: %[[Y:.*]] = alloca i8* +; CHECK-DAG: %[[X2:.*]] = bitcast i8** %[[X]] to i64* +; CHECK-DAG: %[[Y2:.*]] = bitcast i8** %[[Y]] to i64* +; CHECK: %[[V:.*]] = load i64* %[[X2]] +; CHECK-NEXT: store i64 %[[V]], i64* %[[Y2]] +; CHECK-NEXT: %[[C:.*]] = inttoptr i64 %[[V]] to i8* +; CHECK-NEXT: ret i8* %[[S]] +entry: + %x = alloca i8* + %y = alloca i64 + %x1 = bitcast i8** %x to i64* + %y1 = bitcast i64* %y to i8** + call void @scribble_on_i64(i64* %x1) + call void @scribble_on_i64(i64* %y) + %tmp = load i64* %x1 + store i64 %tmp, i64* %y + %p = select i1 %flag, i8** %x, i8** %y1 + %v = load i8** %p + ret i8* %v +} + +define i64 @test84(i1 %flag) { +; Test that we can speculate the load around the select even though they use +; differently typed pointers and requires a ptrtoint cast. +; CHECK-LABEL: @test84( +; CHECK: %[[X:.*]] = alloca i8* +; CHECK-NEXT: %[[Y:.*]] = alloca i8* +; CHECK: %[[V:.*]] = load i8** %[[X]] +; CHECK-NEXT: store i8* %[[V]], i8** %[[Y]] +; CHECK-NEXT: %[[C:.*]] = ptrtoint i8* %[[V]] to i64 +; CHECK-NEXT: ret i64 %[[C]] +entry: + %x = alloca i8* + %y = alloca i64 + %x1 = bitcast i8** %x to i64* + %y1 = bitcast i64* %y to i8** + call void @scribble_on_i64(i64* %x1) + call void @scribble_on_i64(i64* %y) + %tmp = load i8** %x + store i8* %tmp, i8** %y1 + %p = select i1 %flag, i64* %x1, i64* %y + %v = load i64* %p + ret i64 %v +} + +define i8* @test85(i1 %flag) { +; Test that we can't speculate the load around the select. The load of the +; pointer doesn't load all of the stored integer bits. We could fix this, but it +; would require endianness checks and other nastiness. +; CHECK-LABEL: @test85( +; CHECK: %[[T:.*]] = load i128* +; CHECK-NEXT: store i128 %[[T]], i128* +; CHECK-NEXT: %[[X:.*]] = load i8** +; CHECK-NEXT: %[[Y:.*]] = load i8** +; CHECK-NEXT: %[[V:.*]] = select i1 %flag, i8* %[[X]], i8* %[[Y]] +; CHECK-NEXT: ret i8* %[[V]] +entry: + %x = alloca [2 x i8*] + %y = alloca i128 + %x1 = bitcast [2 x i8*]* %x to i8** + %x2 = bitcast i8** %x1 to i128* + %y1 = bitcast i128* %y to i8** + call void @scribble_on_i128(i128* %x2) + call void @scribble_on_i128(i128* %y) + %tmp = load i128* %x2 + store i128 %tmp, i128* %y + %p = select i1 %flag, i8** %x1, i8** %y1 + %v = load i8** %p + ret i8* %v +} + +define i128 @test86(i1 %flag) { +; Test that we can't speculate the load around the select when the integer size +; is larger than the pointer size. The store of the pointer doesn't store to all +; the bits of the integer. +; +; CHECK-LABEL: @test86( +; CHECK: %[[T:.*]] = load i8** +; CHECK-NEXT: store i8* %[[T]], i8** +; CHECK-NEXT: %[[X:.*]] = load i128* +; CHECK-NEXT: %[[Y:.*]] = load i128* +; CHECK-NEXT: %[[V:.*]] = select i1 %flag, i128 %[[X]], i128 %[[Y]] +; CHECK-NEXT: ret i128 %[[V]] +entry: + %x = alloca [2 x i8*] + %y = alloca i128 + %x1 = bitcast [2 x i8*]* %x to i8** + %x2 = bitcast i8** %x1 to i128* + %y1 = bitcast i128* %y to i8** + call void @scribble_on_i128(i128* %x2) + call void @scribble_on_i128(i128* %y) + %tmp = load i8** %x1 + store i8* %tmp, i8** %y1 + %p = select i1 %flag, i128* %x2, i128* %y + %v = load i128* %p + ret i128 %v +} diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll index 5586bb652783..0b5b5deb68c5 100644 --- a/test/Transforms/InstCombine/shift.ll +++ b/test/Transforms/InstCombine/shift.ll @@ -57,7 +57,7 @@ define <4 x i32> @test5_zero_vector(<4 x i32> %A) { define <4 x i32> @test5_non_splat_vector(<4 x i32> %A) { ; CHECK-LABEL: @test5_non_splat_vector( ; CHECK-NOT: ret <4 x i32> undef - %B = shl <4 x i32> %A, <i32 32, i32 1, i32 2, i32 3> + %B = lshr <4 x i32> %A, <i32 32, i32 1, i32 2, i32 3> ret <4 x i32> %B } @@ -84,14 +84,14 @@ define <4 x i32> @test5a_non_splat_vector(<4 x i32> %A) { define i32 @test5b() { ; CHECK-LABEL: @test5b( -; CHECK: ret i32 -1 +; CHECK: ret i32 0 %B = ashr i32 undef, 2 ;; top two bits must be equal, so not undef ret i32 %B } define i32 @test5b2(i32 %A) { ; CHECK-LABEL: @test5b2( -; CHECK: ret i32 -1 +; CHECK: ret i32 0 %B = ashr i32 undef, %A ;; top %A bits must be equal, so not undef ret i32 %B } @@ -738,67 +738,49 @@ define i32 @test56(i32 %x) { define i32 @test57(i32 %x) { - %shr = lshr i32 %x, 1 - %shl = shl i32 %shr, 4 - %and = and i32 %shl, 16 - ret i32 %and -; CHECK-LABEL: @test57( -; CHECK: shl i32 %x, 3 -} - -define i32 @test58(i32 %x) { - %shr = lshr i32 %x, 1 - %shl = shl i32 %shr, 4 - %or = or i32 %shl, 8 - ret i32 %or -; CHECK-LABEL: @test58( -; CHECK: shl i32 %x, 3 -} - -define i32 @test59(i32 %x) { %shr = ashr i32 %x, 1 %shl = shl i32 %shr, 4 %or = or i32 %shl, 7 ret i32 %or -; CHECK-LABEL: @test59( +; CHECK-LABEL: @test57( ; CHECK: %shl = shl i32 %shr1, 4 } -define i32 @test60(i32 %x) { +define i32 @test58(i32 %x) { %shr = ashr i32 %x, 4 %shl = shl i32 %shr, 1 %or = or i32 %shl, 1 ret i32 %or -; CHECK-LABEL: @test60( +; CHECK-LABEL: @test58( ; CHECK: ashr i32 %x, 3 } -define i32 @test61(i32 %x) { +define i32 @test59(i32 %x) { %shr = ashr i32 %x, 4 %shl = shl i32 %shr, 1 %or = or i32 %shl, 2 ret i32 %or -; CHECK-LABEL: @test61( +; CHECK-LABEL: @test59( ; CHECK: ashr i32 %x, 4 } ; propagate "exact" trait -define i32 @test62(i32 %x) { +define i32 @test60(i32 %x) { %shr = ashr exact i32 %x, 4 %shl = shl i32 %shr, 1 %or = or i32 %shl, 1 ret i32 %or -; CHECK-LABEL: @test62( +; CHECK-LABEL: @test60( ; CHECK: ashr exact i32 %x, 3 } ; PR17026 -; CHECK-LABEL: @test63( +; CHECK-LABEL: @test61( ; CHECK-NOT: sh ; CHECK: ret -define void @test63(i128 %arg) { +define void @test61(i128 %arg) { bb: br i1 undef, label %bb1, label %bb12 @@ -830,29 +812,29 @@ bb12: ; preds = %bb11, %bb8, %bb ret void } -define i32 @test64(i32 %a) { -; CHECK-LABEL: @test64( +define i32 @test62(i32 %a) { +; CHECK-LABEL: @test62( ; CHECK-NEXT: ret i32 undef %b = ashr i32 %a, 32 ; shift all bits out ret i32 %b } -define <4 x i32> @test64_splat_vector(<4 x i32> %a) { -; CHECK-LABEL: @test64_splat_vector +define <4 x i32> @test62_splat_vector(<4 x i32> %a) { +; CHECK-LABEL: @test62_splat_vector ; CHECK-NEXT: ret <4 x i32> undef %b = ashr <4 x i32> %a, <i32 32, i32 32, i32 32, i32 32> ; shift all bits out ret <4 x i32> %b } -define <4 x i32> @test64_non_splat_vector(<4 x i32> %a) { -; CHECK-LABEL: @test64_non_splat_vector +define <4 x i32> @test62_non_splat_vector(<4 x i32> %a) { +; CHECK-LABEL: @test62_non_splat_vector ; CHECK-NOT: ret <4 x i32> undef %b = ashr <4 x i32> %a, <i32 32, i32 0, i32 1, i32 2> ; shift all bits out ret <4 x i32> %b } -define <2 x i65> @test_65(<2 x i64> %t) { -; CHECK-LABEL: @test_65 +define <2 x i65> @test_63(<2 x i64> %t) { +; CHECK-LABEL: @test_63 %a = zext <2 x i64> %t to <2 x i65> %sext = shl <2 x i65> %a, <i65 33, i65 33> %b = ashr <2 x i65> %sext, <i65 33, i65 33> diff --git a/test/Transforms/InstCombine/signext.ll b/test/Transforms/InstCombine/signext.ll index d7004977cd63..3a714d7046d3 100644 --- a/test/Transforms/InstCombine/signext.ll +++ b/test/Transforms/InstCombine/signext.ll @@ -34,54 +34,45 @@ define i32 @test3(i16 %P) { ; CHECK: ret i32 %tmp.5 } -define i32 @test4(i16 %P) { - %tmp.1 = zext i16 %P to i32 ; <i32> [#uses=1] - %tmp.4 = xor i32 %tmp.1, 32768 ; <i32> [#uses=1] - %tmp.5 = add i32 %tmp.4, -32768 ; <i32> [#uses=1] - ret i32 %tmp.5 -; CHECK-LABEL: @test4( -; CHECK: %tmp.5 = sext i16 %P to i32 -; CHECK: ret i32 %tmp.5 -} - -define i32 @test5(i32 %x) { +define i32 @test4(i32 %x) { %tmp.1 = and i32 %x, 255 ; <i32> [#uses=1] %tmp.2 = xor i32 %tmp.1, 128 ; <i32> [#uses=1] %tmp.3 = add i32 %tmp.2, -128 ; <i32> [#uses=1] ret i32 %tmp.3 -; CHECK-LABEL: @test5( +; CHECK-LABEL: @test4( ; CHECK: %sext = shl i32 %x, 24 ; CHECK: %tmp.3 = ashr exact i32 %sext, 24 ; CHECK: ret i32 %tmp.3 } -define i32 @test6(i32 %x) { +define i32 @test5(i32 %x) { %tmp.2 = shl i32 %x, 16 ; <i32> [#uses=1] %tmp.4 = ashr i32 %tmp.2, 16 ; <i32> [#uses=1] ret i32 %tmp.4 -; CHECK-LABEL: @test6( +; CHECK-LABEL: @test5( ; CHECK: %tmp.2 = shl i32 %x, 16 ; CHECK: %tmp.4 = ashr exact i32 %tmp.2, 16 ; CHECK: ret i32 %tmp.4 } -define i32 @test7(i16 %P) { +define i32 @test6(i16 %P) { %tmp.1 = zext i16 %P to i32 ; <i32> [#uses=1] %sext1 = shl i32 %tmp.1, 16 ; <i32> [#uses=1] %tmp.5 = ashr i32 %sext1, 16 ; <i32> [#uses=1] ret i32 %tmp.5 -; CHECK-LABEL: @test7( +; CHECK-LABEL: @test6( ; CHECK: %tmp.5 = sext i16 %P to i32 ; CHECK: ret i32 %tmp.5 } -define i32 @test8(i32 %x) nounwind readnone { +define i32 @test7(i32 %x) nounwind readnone { entry: %shr = lshr i32 %x, 5 ; <i32> [#uses=1] %xor = xor i32 %shr, 67108864 ; <i32> [#uses=1] %sub = add i32 %xor, -67108864 ; <i32> [#uses=1] ret i32 %sub -; CHECK-LABEL: @test8( +; CHECK-LABEL: @test7( ; CHECK: %sub = ashr i32 %x, 5 ; CHECK: ret i32 %sub } + diff --git a/test/Transforms/InstCombine/statepoint.ll b/test/Transforms/InstCombine/statepoint.ll new file mode 100644 index 000000000000..bee219db9c12 --- /dev/null +++ b/test/Transforms/InstCombine/statepoint.ll @@ -0,0 +1,52 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +; These tests check the optimizations specific to +; pointers being relocated at a statepoint. + + +declare void @func() + +define i1 @test_negative(i32 addrspace(1)* %p) { +entry: + %safepoint_token = tail call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* %p) + %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4) + %cmp = icmp eq i32 addrspace(1)* %pnew, null + ret i1 %cmp +; CHECK-LABEL: test_negative +; CHECK: %pnew = call i32 addrspace(1)* +; CHECK: ret i1 %cmp +} + +define i1 @test_nonnull(i32 addrspace(1)* nonnull %p) { +entry: + %safepoint_token = tail call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* %p) + %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4) + %cmp = icmp eq i32 addrspace(1)* %pnew, null + ret i1 %cmp +; CHECK-LABEL: test_nonnull +; CHECK: ret i1 false +} + +define i1 @test_null() { +entry: + %safepoint_token = tail call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* null) + %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4) + %cmp = icmp eq i32 addrspace(1)* %pnew, null + ret i1 %cmp +; CHECK-LABEL: test_null +; CHECK-NOT: %pnew +; CHECK: ret i1 true +} + +define i1 @test_undef() { +entry: + %safepoint_token = tail call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* undef) + %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4) + %cmp = icmp eq i32 addrspace(1)* %pnew, null + ret i1 %cmp +; CHECK-LABEL: test_undef +; CHECK-NOT: %pnew +; CHECK: ret i1 undef +} + +declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()*, i32, i32, ...) +declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32) #3 diff --git a/test/Transforms/InstCombine/store.ll b/test/Transforms/InstCombine/store.ll index b64c800e546c..0bb175923e98 100644 --- a/test/Transforms/InstCombine/store.ll +++ b/test/Transforms/InstCombine/store.ll @@ -113,8 +113,8 @@ for.end: ; preds = %for.cond ; CHECK-NEXT: store i32 %storemerge, i32* %gi, align 4, !tbaa !0 } -!0 = metadata !{metadata !4, metadata !4, i64 0} -!1 = metadata !{metadata !"omnipotent char", metadata !2} -!2 = metadata !{metadata !"Simple C/C++ TBAA"} -!3 = metadata !{metadata !"float", metadata !1} -!4 = metadata !{metadata !"int", metadata !1} +!0 = !{!4, !4, i64 0} +!1 = !{!"omnipotent char", !2} +!2 = !{!"Simple C/C++ TBAA"} +!3 = !{!"float", !1} +!4 = !{!"int", !1} diff --git a/test/Transforms/InstCombine/strcmp-1.ll b/test/Transforms/InstCombine/strcmp-1.ll index fc58ffcb8cb0..9bbd7dbe7da8 100644 --- a/test/Transforms/InstCombine/strcmp-1.ll +++ b/test/Transforms/InstCombine/strcmp-1.ll @@ -15,7 +15,7 @@ define i32 @test1(i8* %str2) { ; CHECK-LABEL: @test1( ; CHECK: %strcmpload = load i8* %str ; CHECK: %1 = zext i8 %strcmpload to i32 -; CHECK: %2 = sub i32 0, %1 +; CHECK: %2 = sub nsw i32 0, %1 ; CHECK: ret i32 %2 %str1 = getelementptr inbounds [1 x i8]* @null, i32 0, i32 0 diff --git a/test/Transforms/InstCombine/strncmp-1.ll b/test/Transforms/InstCombine/strncmp-1.ll index df30dd100443..49b095554c2c 100644 --- a/test/Transforms/InstCombine/strncmp-1.ll +++ b/test/Transforms/InstCombine/strncmp-1.ll @@ -15,7 +15,7 @@ define i32 @test1(i8* %str2) { ; CHECK-LABEL: @test1( ; CHECK: %strcmpload = load i8* %str ; CHECK: %1 = zext i8 %strcmpload to i32 -; CHECK: %2 = sub i32 0, %1 +; CHECK: %2 = sub nsw i32 0, %1 ; CHECK: ret i32 %2 %str1 = getelementptr inbounds [1 x i8]* @null, i32 0, i32 0 @@ -73,7 +73,7 @@ define i32 @test6(i8* %str1, i8* %str2) { ; CHECK: [[ZEXT1:%[a-z]+]] = zext i8 [[LOAD1]] to i32 ; CHECK: [[LOAD2:%[a-z]+]] = load i8* %str2, align 1 ; CHECK: [[ZEXT2:%[a-z]+]] = zext i8 [[LOAD2]] to i32 -; CHECK: [[RET:%[a-z]+]] = sub i32 [[ZEXT1]], [[ZEXT2]] +; CHECK: [[RET:%[a-z]+]] = sub nsw i32 [[ZEXT1]], [[ZEXT2]] ; CHECK: ret i32 [[RET]] %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 1) diff --git a/test/Transforms/InstCombine/struct-assign-tbaa.ll b/test/Transforms/InstCombine/struct-assign-tbaa.ll index c80e31ae3ddc..4e4b3f2a1a88 100644 --- a/test/Transforms/InstCombine/struct-assign-tbaa.ll +++ b/test/Transforms/InstCombine/struct-assign-tbaa.ll @@ -35,12 +35,12 @@ define i32 (i8*, i32*, double*)*** @test2() { ret i32 (i8*, i32*, double*)*** %tmp2 } -; CHECK: !0 = metadata !{metadata !1, metadata !1, i64 0} -; CHECK: !1 = metadata !{metadata !"float", metadata !2} - -!0 = metadata !{metadata !"Simple C/C++ TBAA"} -!1 = metadata !{metadata !"omnipotent char", metadata !0} -!2 = metadata !{metadata !5, metadata !5, i64 0} -!3 = metadata !{i64 0, i64 4, metadata !2} -!4 = metadata !{i64 0, i64 8, null} -!5 = metadata !{metadata !"float", metadata !0} +; CHECK: !0 = !{!1, !1, i64 0} +; CHECK: !1 = !{!"float", !2} + +!0 = !{!"Simple C/C++ TBAA"} +!1 = !{!"omnipotent char", !0} +!2 = !{!5, !5, i64 0} +!3 = !{i64 0, i64 4, !2} +!4 = !{i64 0, i64 8, null} +!5 = !{!"float", !0} diff --git a/test/Transforms/InstCombine/sub-xor.ll b/test/Transforms/InstCombine/sub-xor.ll index e7aff00ba8d0..3a24074e72a7 100644 --- a/test/Transforms/InstCombine/sub-xor.ll +++ b/test/Transforms/InstCombine/sub-xor.ll @@ -32,7 +32,7 @@ define i32 @test3(i32 %x) nounwind { ; CHECK-LABEL: @test3( ; CHECK-NEXT: and i32 %x, 31 -; CHECK-NEXT: sub i32 73, %and +; CHECK-NEXT: sub nsw i32 73, %and ; CHECK-NEXT: ret } diff --git a/test/Transforms/InstCombine/sub.ll b/test/Transforms/InstCombine/sub.ll index 67b7c4996b07..0e421f75f139 100644 --- a/test/Transforms/InstCombine/sub.ll +++ b/test/Transforms/InstCombine/sub.ll @@ -142,8 +142,9 @@ define i32 @test15(i32 %A, i32 %B) { %D = srem i32 %B, %C ret i32 %D ; CHECK-LABEL: @test15( -; CHECK: %D = srem i32 %B, %A -; CHECK: ret i32 %D +; CHECK: %[[sub:.*]] = sub i32 0, %A +; CHECK-NEXT: %[[rem:.*]] = srem i32 %B, %[[sub]] +; CHECK: ret i32 %[[rem]] } define i32 @test16(i32 %A) { @@ -464,3 +465,88 @@ define i32 @test38(i32 %A) { ; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[ICMP]] to i32 ; CHECK-NEXT: ret i32 [[SEXT]] } + +define i32 @test39(i32 %A, i32 %x) { + %B = sub i32 0, %A + %C = sub nsw i32 %x, %B + ret i32 %C +; CHECK-LABEL: @test39( +; CHECK: %C = add i32 %x, %A +; CHECK: ret i32 %C +} + +define i16 @test40(i16 %a, i16 %b) { + %ashr = ashr i16 %a, 1 + %ashr1 = ashr i16 %b, 1 + %sub = sub i16 %ashr, %ashr1 + ret i16 %sub +; CHECK-LABEL: @test40( +; CHECK-NEXT: [[ASHR:%.*]] = ashr i16 %a, 1 +; CHECK-NEXT: [[ASHR1:%.*]] = ashr i16 %b, 1 +; CHECK-NEXT: [[RET:%.*]] = sub nsw i16 [[ASHR]], [[ASHR1]] +; CHECK: ret i16 [[RET]] +} + +define i32 @test41(i16 %a, i16 %b) { + %conv = sext i16 %a to i32 + %conv1 = sext i16 %b to i32 + %sub = sub i32 %conv, %conv1 + ret i32 %sub +; CHECK-LABEL: @test41( +; CHECK-NEXT: [[SEXT:%.*]] = sext i16 %a to i32 +; CHECK-NEXT: [[SEXT1:%.*]] = sext i16 %b to i32 +; CHECK-NEXT: [[RET:%.*]] = sub nsw i32 [[SEXT]], [[SEXT1]] +; CHECK: ret i32 [[RET]] +} + +define i4 @test42(i4 %x, i4 %y) { + %a = and i4 %y, 7 + %b = and i4 %x, 7 + %c = sub i4 %a, %b + ret i4 %c +; CHECK-LABEL: @test42( +; CHECK-NEXT: [[AND:%.*]] = and i4 %y, 7 +; CHECK-NEXT: [[AND1:%.*]] = and i4 %x, 7 +; CHECK-NEXT: [[RET:%.*]] = sub nsw i4 [[AND]], [[AND1]] +; CHECK: ret i4 [[RET]] +} + +define i4 @test43(i4 %x, i4 %y) { + %a = or i4 %x, -8 + %b = and i4 %y, 7 + %c = sub i4 %a, %b + ret i4 %c +; CHECK-LABEL: @test43( +; CHECK-NEXT: [[OR:%.*]] = or i4 %x, -8 +; CHECK-NEXT: [[AND:%.*]] = and i4 %y, 7 +; CHECK-NEXT: [[RET:%.*]] = sub nuw i4 [[OR]], [[AND]] +; CHECK: ret i4 [[RET]] +} + +define i32 @test44(i32 %x) { + %sub = sub nsw i32 %x, 32768 + ret i32 %sub +; CHECK-LABEL: @test44( +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 %x, -32768 +; CHECK: ret i32 [[ADD]] +} + +define i32 @test45(i32 %x, i32 %y) { + %or = or i32 %x, %y + %xor = xor i32 %x, %y + %sub = sub i32 %or, %xor + ret i32 %sub +; CHECK-LABEL: @test45( +; CHECK-NEXT: %sub = and i32 %x, %y +; CHECK: ret i32 %sub +} + +define i32 @test46(i32 %x, i32 %y) { + %or = or i32 %x, %y + %sub = sub i32 %or, %x + ret i32 %sub +; CHECK-LABEL: @test46( +; CHECK-NEXT: %x.not = xor i32 %x, -1 +; CHECK-NEXT: %sub = and i32 %y, %x.not +; CHECK: ret i32 %sub +} diff --git a/test/Transforms/InstCombine/unordered-fcmp-select.ll b/test/Transforms/InstCombine/unordered-fcmp-select.ll new file mode 100644 index 000000000000..0eb729047e71 --- /dev/null +++ b/test/Transforms/InstCombine/unordered-fcmp-select.ll @@ -0,0 +1,125 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +; CHECK-LABEL: @select_max_ugt( +; CHECK: %cmp.inv = fcmp ole float %a, %b +; CHECK-NEXT: %sel = select i1 %cmp.inv, float %b, float %a +; CHECK-NEXT: ret float %sel +define float @select_max_ugt(float %a, float %b) { + %cmp = fcmp ugt float %a, %b + %sel = select i1 %cmp, float %a, float %b + ret float %sel +} + +; CHECK-LABEL: @select_max_uge( +; CHECK: %cmp.inv = fcmp olt float %a, %b +; CHECK-NEXT: %sel = select i1 %cmp.inv, float %b, float %a +; CHECK-NEXT: ret float %sel +define float @select_max_uge(float %a, float %b) { + %cmp = fcmp uge float %a, %b + %sel = select i1 %cmp, float %a, float %b + ret float %sel +} + +; CHECK-LABEL: @select_min_ugt( +; CHECK: %cmp.inv = fcmp ole float %a, %b +; CHECK-NEXT: %sel = select i1 %cmp.inv, float %a, float %b +; CHECK-NEXT: ret float %sel +define float @select_min_ugt(float %a, float %b) { + %cmp = fcmp ugt float %a, %b + %sel = select i1 %cmp, float %b, float %a + ret float %sel +} + +; CHECK-LABEL: @select_min_uge( +; CHECK: %cmp.inv = fcmp olt float %a, %b +; CHECK-NEXT: %sel = select i1 %cmp.inv, float %a, float %b +; CHECK-NEXT: ret float %sel +define float @select_min_uge(float %a, float %b) { + %cmp = fcmp uge float %a, %b + %sel = select i1 %cmp, float %b, float %a + ret float %sel +} + +; CHECK-LABEL: @select_max_ult( +; CHECK: %cmp.inv = fcmp oge float %a, %b +; CHECK-NEXT: %sel = select i1 %cmp.inv, float %a, float %b +; CHECK-NEXT: ret float %sel +define float @select_max_ult(float %a, float %b) { + %cmp = fcmp ult float %a, %b + %sel = select i1 %cmp, float %b, float %a + ret float %sel +} + +; CHECK-LABEL: @select_max_ule( +; CHECK: %cmp.inv = fcmp ogt float %a, %b +; CHECK-NEXT: %sel = select i1 %cmp.inv, float %a, float %b +; CHECK: ret float %sel +define float @select_max_ule(float %a, float %b) { + %cmp = fcmp ule float %a, %b + %sel = select i1 %cmp, float %b, float %a + ret float %sel +} + +; CHECK-LABEL: @select_min_ult( +; CHECK: %cmp.inv = fcmp oge float %a, %b +; CHECK-NEXT: %sel = select i1 %cmp.inv, float %b, float %a +; CHECK-NEXT: ret float %sel +define float @select_min_ult(float %a, float %b) { + %cmp = fcmp ult float %a, %b + %sel = select i1 %cmp, float %a, float %b + ret float %sel +} + +; CHECK-LABEL: @select_min_ule( +; CHECK: %cmp.inv = fcmp ogt float %a, %b +; CHECK-NEXT: %sel = select i1 %cmp.inv, float %b, float %a +; CHECK-NEXT: ret float %sel +define float @select_min_ule(float %a, float %b) { + %cmp = fcmp ule float %a, %b + %sel = select i1 %cmp, float %a, float %b + ret float %sel +} + +; CHECK-LABEL: @select_fcmp_une( +; CHECK: %cmp.inv = fcmp oeq float %a, %b +; CHECK-NEXT: %sel = select i1 %cmp.inv, float %b, float %a +; CHECK-NEXT: ret float %sel +define float @select_fcmp_une(float %a, float %b) { + %cmp = fcmp une float %a, %b + %sel = select i1 %cmp, float %a, float %b + ret float %sel +} + +; CHECK-LABEL: @select_fcmp_ueq +; CHECK: %cmp.inv = fcmp one float %a, %b +; CHECK-NEXT: %sel = select i1 %cmp.inv, float %b, float %a +; CHECK-NEXT: ret float %sel +define float @select_fcmp_ueq(float %a, float %b) { + %cmp = fcmp ueq float %a, %b + %sel = select i1 %cmp, float %a, float %b + ret float %sel +} + +declare void @foo(i1) + +; CHECK-LABEL: @select_max_ugt_2_use_cmp( +; CHECK: fcmp ugt +; CHECK-NOT: fcmp +; CHECK: ret +define float @select_max_ugt_2_use_cmp(float %a, float %b) { + %cmp = fcmp ugt float %a, %b + call void @foo(i1 %cmp) + %sel = select i1 %cmp, float %a, float %b + ret float %sel +} + +; CHECK-LABEL: @select_min_uge_2_use_cmp( +; CHECK: fcmp uge +; CHECK-NOT: fcmp +; CHECK: ret +define float @select_min_uge_2_use_cmp(float %a, float %b) { + %cmp = fcmp uge float %a, %b + call void @foo(i1 %cmp) + %sel = select i1 %cmp, float %b, float %a + ret float %sel +} diff --git a/test/Transforms/InstCombine/vec_demanded_elts.ll b/test/Transforms/InstCombine/vec_demanded_elts.ll index 41d2b292eeff..00a029aeab78 100644 --- a/test/Transforms/InstCombine/vec_demanded_elts.ll +++ b/test/Transforms/InstCombine/vec_demanded_elts.ll @@ -303,6 +303,33 @@ define <2 x i64> @testInsertDisjointRange_2(<2 x i64> %v, <2 x i64> %i) { ret <2 x i64> %2 } +; CHECK: define <2 x i64> @testZeroLength(<2 x i64> %v, <2 x i64> %i) +define <2 x i64> @testZeroLength(<2 x i64> %v, <2 x i64> %i) { +; CHECK: ret <2 x i64> %i + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 0, i8 0) + ret <2 x i64> %1 +} + +; CHECK: define <2 x i64> @testUndefinedInsertq_1(<2 x i64> %v, <2 x i64> %i) +define <2 x i64> @testUndefinedInsertq_1(<2 x i64> %v, <2 x i64> %i) { +; CHECK: ret <2 x i64> undef + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 0, i8 16) + ret <2 x i64> %1 +} + +; CHECK: define <2 x i64> @testUndefinedInsertq_2(<2 x i64> %v, <2 x i64> %i) +define <2 x i64> @testUndefinedInsertq_2(<2 x i64> %v, <2 x i64> %i) { +; CHECK: ret <2 x i64> undef + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 48, i8 32) + ret <2 x i64> %1 +} + +; CHECK: define <2 x i64> @testUndefinedInsertq_3(<2 x i64> %v, <2 x i64> %i) +define <2 x i64> @testUndefinedInsertq_3(<2 x i64> %v, <2 x i64> %i) { +; CHECK: ret <2 x i64> undef + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 64, i8 16) + ret <2 x i64> %1 +} ; CHECK: declare <2 x i64> @llvm.x86.sse4a.insertqi declare <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64>, <2 x i64>, i8, i8) nounwind diff --git a/test/Transforms/InstCombine/vsx-unaligned.ll b/test/Transforms/InstCombine/vsx-unaligned.ll new file mode 100644 index 000000000000..26e04268f446 --- /dev/null +++ b/test/Transforms/InstCombine/vsx-unaligned.ll @@ -0,0 +1,44 @@ +; Verify that we can create unaligned loads and stores from VSX intrinsics. + +; RUN: opt < %s -instcombine -S | FileCheck %s + +target triple = "powerpc64-unknown-linux-gnu" + +@vf = common global <4 x float> zeroinitializer, align 1 +@res_vf = common global <4 x float> zeroinitializer, align 1 +@vd = common global <2 x double> zeroinitializer, align 1 +@res_vd = common global <2 x double> zeroinitializer, align 1 + +define void @test1() { +entry: + %t1 = alloca <4 x float>*, align 8 + %t2 = alloca <2 x double>*, align 8 + store <4 x float>* @vf, <4 x float>** %t1, align 8 + %0 = load <4 x float>** %t1, align 8 + %1 = bitcast <4 x float>* %0 to i8* + %2 = call <4 x i32> @llvm.ppc.vsx.lxvw4x(i8* %1) + store <4 x float>* @res_vf, <4 x float>** %t1, align 8 + %3 = load <4 x float>** %t1, align 8 + %4 = bitcast <4 x float>* %3 to i8* + call void @llvm.ppc.vsx.stxvw4x(<4 x i32> %2, i8* %4) + store <2 x double>* @vd, <2 x double>** %t2, align 8 + %5 = load <2 x double>** %t2, align 8 + %6 = bitcast <2 x double>* %5 to i8* + %7 = call <2 x double> @llvm.ppc.vsx.lxvd2x(i8* %6) + store <2 x double>* @res_vd, <2 x double>** %t2, align 8 + %8 = load <2 x double>** %t2, align 8 + %9 = bitcast <2 x double>* %8 to i8* + call void @llvm.ppc.vsx.stxvd2x(<2 x double> %7, i8* %9) + ret void +} + +; CHECK-LABEL: @test1 +; CHECK: %0 = load <4 x i32>* bitcast (<4 x float>* @vf to <4 x i32>*), align 1 +; CHECK: store <4 x i32> %0, <4 x i32>* bitcast (<4 x float>* @res_vf to <4 x i32>*), align 1 +; CHECK: %1 = load <2 x double>* @vd, align 1 +; CHECK: store <2 x double> %1, <2 x double>* @res_vd, align 1 + +declare <4 x i32> @llvm.ppc.vsx.lxvw4x(i8*) +declare void @llvm.ppc.vsx.stxvw4x(<4 x i32>, i8*) +declare <2 x double> @llvm.ppc.vsx.lxvd2x(i8*) +declare void @llvm.ppc.vsx.stxvd2x(<2 x double>, i8*) diff --git a/test/Transforms/InstCombine/xor.ll b/test/Transforms/InstCombine/xor.ll index 3722697f9892..c8debcbac226 100644 --- a/test/Transforms/InstCombine/xor.ll +++ b/test/Transforms/InstCombine/xor.ll @@ -1,50 +1,70 @@ ; This test makes sure that these instructions are properly eliminated. ; ; RUN: opt < %s -instcombine -S | \ -; RUN: not grep "xor " +; RUN: FileCheck %s ; END. @G1 = global i32 0 ; <i32*> [#uses=1] @G2 = global i32 0 ; <i32*> [#uses=1] define i1 @test0(i1 %A) { +; CHECK-LABEL: @test0( +; CHECK-NEXT: ret i1 %A %B = xor i1 %A, false ; <i1> [#uses=1] ret i1 %B } define i32 @test1(i32 %A) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: ret i32 %A %B = xor i32 %A, 0 ; <i32> [#uses=1] ret i32 %B } define i1 @test2(i1 %A) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: ret i1 false %B = xor i1 %A, %A ; <i1> [#uses=1] ret i1 %B } define i32 @test3(i32 %A) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: ret i32 0 %B = xor i32 %A, %A ; <i32> [#uses=1] ret i32 %B } define i32 @test4(i32 %A) { +; CHECK-LABEL: @test4( +; CHECK-NEXT: ret i32 -1 %NotA = xor i32 -1, %A ; <i32> [#uses=1] %B = xor i32 %A, %NotA ; <i32> [#uses=1] ret i32 %B } define i32 @test5(i32 %A) { +; CHECK-LABEL: @test5( +; CHECK-NEXT: %1 = and i32 %A, -124 +; CHECK-NEXT: ret i32 %1 %t1 = or i32 %A, 123 ; <i32> [#uses=1] %r = xor i32 %t1, 123 ; <i32> [#uses=1] ret i32 %r } define i8 @test6(i8 %A) { +; CHECK-LABEL: @test6( +; CHECK-NEXT: ret i8 %A %B = xor i8 %A, 17 ; <i8> [#uses=1] %C = xor i8 %B, 17 ; <i8> [#uses=1] ret i8 %C } define i32 @test7(i32 %A, i32 %B) { +; CHECK-LABEL: @test7( +; CHECK-NEXT: %A1 = and i32 %A, 7 +; CHECK-NEXT: %B1 = and i32 %B, 128 +; CHECK-NEXT: %C11 = or i32 %A1, %B1 +; CHECK-NEXT: ret i32 %C11 %A1 = and i32 %A, 7 ; <i32> [#uses=1] %B1 = and i32 %B, 128 ; <i32> [#uses=1] %C1 = xor i32 %A1, %B1 ; <i32> [#uses=1] @@ -52,6 +72,8 @@ define i32 @test7(i32 %A, i32 %B) { } define i8 @test8(i1 %c) { +; CHECK-LABEL: @test8( +; CHECK: br i1 %c, label %False, label %True %d = xor i1 %c, true ; <i1> [#uses=1] br i1 %d, label %True, label %False @@ -63,30 +85,47 @@ False: ; preds = %0 } define i1 @test9(i8 %A) { +; CHECK-LABEL: @test9( +; CHECK-NEXT: %C = icmp eq i8 %A, 89 +; CHECK-NEXT: ret i1 %C %B = xor i8 %A, 123 ; <i8> [#uses=1] %C = icmp eq i8 %B, 34 ; <i1> [#uses=1] ret i1 %C } define i8 @test10(i8 %A) { +; CHECK-LABEL: @test10( +; CHECK-NEXT: %B = and i8 %A, 3 +; CHECK-NEXT: %C1 = or i8 %B, 4 +; CHECK-NEXT: ret i8 %C1 %B = and i8 %A, 3 ; <i8> [#uses=1] %C = xor i8 %B, 4 ; <i8> [#uses=1] ret i8 %C } define i8 @test11(i8 %A) { +; CHECK-LABEL: @test11( +; CHECK-NEXT: %B = and i8 %A, -13 +; CHECK-NEXT: %1 = or i8 %B, 8 +; CHECK-NEXT: ret i8 %1 %B = or i8 %A, 12 ; <i8> [#uses=1] %C = xor i8 %B, 4 ; <i8> [#uses=1] ret i8 %C } define i1 @test12(i8 %A) { +; CHECK-LABEL: @test12( +; CHECK-NEXT: %c = icmp ne i8 %A, 4 +; CHECK-NEXT: ret i1 %c %B = xor i8 %A, 4 ; <i8> [#uses=1] %c = icmp ne i8 %B, 0 ; <i1> [#uses=1] ret i1 %c } define i1 @test13(i8 %A, i8 %B) { +; CHECK-LABEL: @test13( +; CHECK-NEXT: %1 = icmp ne i8 %A, %B +; CHECK-NEXT: ret i1 %1 %C = icmp ult i8 %A, %B ; <i1> [#uses=1] %D = icmp ugt i8 %A, %B ; <i1> [#uses=1] %E = xor i1 %C, %D ; <i1> [#uses=1] @@ -94,6 +133,8 @@ define i1 @test13(i8 %A, i8 %B) { } define i1 @test14(i8 %A, i8 %B) { +; CHECK-LABEL: @test14( +; CHECK-NEXT: ret i1 true %C = icmp eq i8 %A, %B ; <i1> [#uses=1] %D = icmp ne i8 %B, %A ; <i1> [#uses=1] %E = xor i1 %C, %D ; <i1> [#uses=1] @@ -101,36 +142,54 @@ define i1 @test14(i8 %A, i8 %B) { } define i32 @test15(i32 %A) { +; CHECK-LABEL: @test15( +; CHECK-NEXT: %C = sub i32 0, %A +; CHECK-NEXT: ret i32 %C %B = add i32 %A, -1 ; <i32> [#uses=1] %C = xor i32 %B, -1 ; <i32> [#uses=1] ret i32 %C } define i32 @test16(i32 %A) { +; CHECK-LABEL: @test16( +; CHECK-NEXT: %C = sub i32 -124, %A +; CHECK-NEXT: ret i32 %C %B = add i32 %A, 123 ; <i32> [#uses=1] %C = xor i32 %B, -1 ; <i32> [#uses=1] ret i32 %C } define i32 @test17(i32 %A) { +; CHECK-LABEL: @test17( +; CHECK-NEXT: %C = add i32 %A, -124 +; CHECK-NEXT: ret i32 %C %B = sub i32 123, %A ; <i32> [#uses=1] %C = xor i32 %B, -1 ; <i32> [#uses=1] ret i32 %C } define i32 @test18(i32 %A) { +; CHECK-LABEL: @test18( +; CHECK-NEXT: %C = add i32 %A, 124 +; CHECK-NEXT: ret i32 %C %B = xor i32 %A, -1 ; <i32> [#uses=1] %C = sub i32 123, %B ; <i32> [#uses=1] ret i32 %C } define i32 @test19(i32 %A, i32 %B) { +; CHECK-LABEL: @test19( +; CHECK-NEXT: ret i32 %B %C = xor i32 %A, %B ; <i32> [#uses=1] %D = xor i32 %C, %A ; <i32> [#uses=1] ret i32 %D } define void @test20(i32 %A, i32 %B) { +; CHECK-LABEL: @test20( +; CHECK-NEXT: store i32 %B, i32* @G1 +; CHECK-NEXT: store i32 %A, i32* @G2 +; CHECK-NEXT: ret void %tmp.2 = xor i32 %B, %A ; <i32> [#uses=2] %tmp.5 = xor i32 %tmp.2, %B ; <i32> [#uses=2] %tmp.8 = xor i32 %tmp.5, %tmp.2 ; <i32> [#uses=1] @@ -140,12 +199,18 @@ define void @test20(i32 %A, i32 %B) { } define i32 @test21(i1 %C, i32 %A, i32 %B) { +; CHECK-LABEL: @test21( +; CHECK-NEXT: %D = select i1 %C, i32 %B, i32 %A +; CHECK-NEXT: ret i32 %D %C2 = xor i1 %C, true ; <i1> [#uses=1] %D = select i1 %C2, i32 %A, i32 %B ; <i32> [#uses=1] ret i32 %D } define i32 @test22(i1 %X) { +; CHECK-LABEL: @test22( +; CHECK-NEXT: %1 = zext i1 %X to i32 +; CHECK-NEXT: ret i32 %1 %Y = xor i1 %X, true ; <i1> [#uses=1] %Z = zext i1 %Y to i32 ; <i32> [#uses=1] %Q = xor i32 %Z, 1 ; <i32> [#uses=1] @@ -153,18 +218,27 @@ define i32 @test22(i1 %X) { } define i1 @test23(i32 %a, i32 %b) { +; CHECK-LABEL: @test23( +; CHECK-NEXT: %tmp.4 = icmp eq i32 %b, 0 +; CHECK-NEXT: ret i1 %tmp.4 %tmp.2 = xor i32 %b, %a ; <i32> [#uses=1] %tmp.4 = icmp eq i32 %tmp.2, %a ; <i1> [#uses=1] ret i1 %tmp.4 } define i1 @test24(i32 %c, i32 %d) { +; CHECK-LABEL: @test24( +; CHECK-NEXT: %tmp.4 = icmp ne i32 %d, 0 +; CHECK-NEXT: ret i1 %tmp.4 %tmp.2 = xor i32 %d, %c ; <i32> [#uses=1] %tmp.4 = icmp ne i32 %tmp.2, %c ; <i1> [#uses=1] ret i1 %tmp.4 } define i32 @test25(i32 %g, i32 %h) { +; CHECK-LABEL: @test25( +; CHECK-NEXT: %tmp4 = and i32 %h, %g +; CHECK-NEXT: ret i32 %tmp4 %h2 = xor i32 %h, -1 ; <i32> [#uses=1] %tmp2 = and i32 %h2, %g ; <i32> [#uses=1] %tmp4 = xor i32 %tmp2, %g ; <i32> [#uses=1] @@ -172,6 +246,9 @@ define i32 @test25(i32 %g, i32 %h) { } define i32 @test26(i32 %a, i32 %b) { +; CHECK-LABEL: @test26( +; CHECK-NEXT: %tmp4 = and i32 %a, %b +; CHECK-NEXT: ret i32 %tmp4 %b2 = xor i32 %b, -1 ; <i32> [#uses=1] %tmp2 = xor i32 %a, %b2 ; <i32> [#uses=1] %tmp4 = and i32 %tmp2, %a ; <i32> [#uses=1] @@ -179,6 +256,10 @@ define i32 @test26(i32 %a, i32 %b) { } define i32 @test27(i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: @test27( +; CHECK-NEXT: %tmp = icmp eq i32 %b, %c +; CHECK-NEXT: %tmp6 = zext i1 %tmp to i32 +; CHECK-NEXT: ret i32 %tmp6 %tmp2 = xor i32 %d, %b ; <i32> [#uses=1] %tmp5 = xor i32 %d, %c ; <i32> [#uses=1] %tmp = icmp eq i32 %tmp2, %tmp5 ; <i1> [#uses=1] @@ -187,6 +268,9 @@ define i32 @test27(i32 %b, i32 %c, i32 %d) { } define i32 @test28(i32 %indvar) { +; CHECK-LABEL: @test28( +; CHECK-NEXT: %tmp214 = add i32 %indvar, 1 +; CHECK-NEXT: ret i32 %tmp214 %tmp7 = add i32 %indvar, -2147483647 ; <i32> [#uses=1] %tmp214 = xor i32 %tmp7, -2147483648 ; <i32> [#uses=1] ret i32 %tmp214 diff --git a/test/Transforms/InstCombine/xor2.ll b/test/Transforms/InstCombine/xor2.ll index d153e035c899..797c8f39f298 100644 --- a/test/Transforms/InstCombine/xor2.ll +++ b/test/Transforms/InstCombine/xor2.ll @@ -82,3 +82,93 @@ define i32 @test6(i32 %x) { ; CHECK: lshr i32 %x, 16 ; CHECK: ret } + + +; (A | B) ^ (~A) -> (A | ~B) +define i32 @test7(i32 %a, i32 %b) { + %or = or i32 %a, %b + %neg = xor i32 %a, -1 + %xor = xor i32 %or, %neg + ret i32 %xor +; CHECK-LABEL: @test7( +; CHECK-NEXT: %[[b_not:.*]] = xor i32 %b, -1 +; CHECK-NEXT: %[[or:.*]] = or i32 %a, %[[b_not]] +; CHECK-NEXT: ret i32 %[[or]] +} + +; (~A) ^ (A | B) -> (A | ~B) +define i32 @test8(i32 %a, i32 %b) { + %neg = xor i32 %a, -1 + %or = or i32 %a, %b + %xor = xor i32 %neg, %or + ret i32 %xor +; CHECK-LABEL: @test8( +; CHECK-NEXT: %[[b_not:.*]] = xor i32 %b, -1 +; CHECK-NEXT: %[[or:.*]] = or i32 %a, %[[b_not]] +; CHECK-NEXT: ret i32 %[[or]] +} + +; (A & B) ^ (A ^ B) -> (A | B) +define i32 @test9(i32 %b, i32 %c) { + %and = and i32 %b, %c + %xor = xor i32 %b, %c + %xor2 = xor i32 %and, %xor + ret i32 %xor2 +; CHECK-LABEL: @test9( +; CHECK-NEXT: %xor2 = or i32 %b, %c +} + +; (A ^ B) ^ (A & B) -> (A | B) +define i32 @test10(i32 %b, i32 %c) { + %xor = xor i32 %b, %c + %and = and i32 %b, %c + %xor2 = xor i32 %xor, %and + ret i32 %xor2 +; CHECK-LABEL: @test10( +; CHECK-NEXT: %xor2 = or i32 %b, %c +} + +define i32 @test11(i32 %A, i32 %B) { + %xor1 = xor i32 %B, %A + %not = xor i32 %A, -1 + %xor2 = xor i32 %not, %B + %and = and i32 %xor1, %xor2 + ret i32 %and +; CHECK-LABEL: @test11( +; CHECK-NEXT: ret i32 0 +} + +define i32 @test12(i32 %a, i32 %b) { + %negb = xor i32 %b, -1 + %and = and i32 %a, %negb + %nega = xor i32 %a, -1 + %xor = xor i32 %and, %nega + ret i32 %xor +; CHECK-LABEL: @test12( +; CHECK-NEXT: %1 = and i32 %a, %b +; CHECK-NEXT: %xor = xor i32 %1, -1 +} + +define i32 @test13(i32 %a, i32 %b) { + %nega = xor i32 %a, -1 + %negb = xor i32 %b, -1 + %and = and i32 %a, %negb + %xor = xor i32 %nega, %and + ret i32 %xor +; CHECK-LABEL: @test13( +; CHECK-NEXT: %1 = and i32 %a, %b +; CHECK-NEXT: %xor = xor i32 %1, -1 +} + +; (A ^ C) ^ (A | B) -> ((~A) & B) ^ C +define i32 @test14(i32 %a, i32 %b, i32 %c) { + %neg = xor i32 %a, %c + %or = or i32 %a, %b + %xor = xor i32 %neg, %or + ret i32 %xor +; CHECK-LABEL: @test14( +; CHECK-NEXT: %[[not:.*]] = xor i32 %a, -1 +; CHECK-NEXT: %[[and:.*]] = and i32 %[[not]], %b +; CHECK-NEXT: %[[xor:.*]] = xor i32 %[[and]], %c +; CHECK-NEXT: ret i32 %[[xor]] +} diff --git a/test/Transforms/InstMerge/ld_hoist1.ll b/test/Transforms/InstMerge/ld_hoist1.ll new file mode 100644 index 000000000000..715f1b824407 --- /dev/null +++ b/test/Transforms/InstMerge/ld_hoist1.ll @@ -0,0 +1,64 @@ +; Test load hoist +; RUN: opt -basicaa -memdep -mldst-motion -S < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc_linux" + +; Function Attrs: nounwind uwtable +define float* @foo(i32* noalias nocapture readonly %in, float* noalias %out, i32 %size, i32* nocapture readonly %trigger) { +entry: + %cmp11 = icmp eq i32 %size, 0 + br i1 %cmp11, label %for.end, label %for.body.lr.ph + +for.body.lr.ph: ; preds = %entry + %0 = add i32 %size, -1 + br label %for.body + +; CHECK-LABEL: for.body +; CHECK: load +; CHECK: %2 = getelementptr inbounds i32* %in, i64 %indvars.iv +; CHECK: %3 = load i32* %2, align 4 + +for.body: ; preds = %for.body.lr.ph, %for.inc + %indvars.iv = phi i64 [ 0, %for.body.lr.ph ], [ %indvars.iv.next, %for.inc ] + %arrayidx = getelementptr inbounds i32* %trigger, i64 %indvars.iv + %1 = load i32* %arrayidx, align 4 + %cmp1 = icmp sgt i32 %1, 0 + br i1 %cmp1, label %if.then, label %if.else + +; CHECK-LABEL: if.then +if.then: ; preds = %for.body +; This load should be hoisted + %arrayidx3 = getelementptr inbounds i32* %in, i64 %indvars.iv + %2 = load i32* %arrayidx3, align 4 + %conv = sitofp i32 %2 to float + %add = fadd float %conv, 5.000000e-01 + %arrayidx5 = getelementptr inbounds float* %out, i64 %indvars.iv + store float %add, float* %arrayidx5, align 4 + br label %for.inc + +if.else: ; preds = %for.body + %arrayidx7 = getelementptr inbounds float* %out, i64 %indvars.iv + %3 = load float* %arrayidx7, align 4 + %div = fdiv float %3, 3.000000e+00 + store float %div, float* %arrayidx7, align 4 +; This load should be hoisted in spite of store + %arrayidx9 = getelementptr inbounds i32* %in, i64 %indvars.iv + %4 = load i32* %arrayidx9, align 4 + %conv10 = sitofp i32 %4 to float + %add13 = fadd float %div, %conv10 + store float %add13, float* %arrayidx7, align 4 + br label %for.inc + +for.inc: ; preds = %if.then, %if.else + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %lftr.wideiv = trunc i64 %indvars.iv to i32 + %exitcond = icmp ne i32 %lftr.wideiv, %0 + br i1 %exitcond, label %for.body, label %for.cond.for.end_crit_edge + +for.cond.for.end_crit_edge: ; preds = %for.inc + br label %for.end + +for.end: ; preds = %entry, %for.cond.for.end_crit_edge + ret float* %out +} + diff --git a/test/Transforms/InstMerge/st_sink_barrier_call.ll b/test/Transforms/InstMerge/st_sink_barrier_call.ll new file mode 100644 index 000000000000..c158b006bee0 --- /dev/null +++ b/test/Transforms/InstMerge/st_sink_barrier_call.ll @@ -0,0 +1,43 @@ +; Test to make sure that a function call that needs to be a barrier to sinking stores is indeed a barrier. +; Stores sunks into the footer. +; RUN: opt -basicaa -memdep -mldst-motion -S < %s | FileCheck %s +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + +%struct.node = type { i32, %struct.node*, %struct.node*, %struct.node*, i32, i32, i32, i32 } + +declare i32 @foo(i32 %x) + +; Function Attrs: nounwind uwtable +define void @sink_store(%struct.node* nocapture %r, i32 %index) { +entry: + %node.0.in16 = getelementptr inbounds %struct.node* %r, i64 0, i32 2 + %node.017 = load %struct.node** %node.0.in16, align 8 + %index.addr = alloca i32, align 4 + store i32 %index, i32* %index.addr, align 4 + %0 = load i32* %index.addr, align 4 + %cmp = icmp slt i32 %0, 0 + br i1 %cmp, label %if.then, label %if.else + +; CHECK: if.then +if.then: ; preds = %entry + %1 = load i32* %index.addr, align 4 + %p1 = getelementptr inbounds %struct.node* %node.017, i32 0, i32 6 + ; CHECK: store i32 + store i32 %1, i32* %p1, align 4 + br label %if.end + +; CHECK: if.else +if.else: ; preds = %entry + %2 = load i32* %index.addr, align 4 + %add = add nsw i32 %2, 1 + %p3 = getelementptr inbounds %struct.node* %node.017, i32 0, i32 6 + ; CHECK: store i32 + store i32 %add, i32* %p3, align 4 + call i32 @foo(i32 5) ;barrier + br label %if.end + +; CHECK: if.end +if.end: ; preds = %if.else, %if.then +; CHECK-NOT: store + ret void +} diff --git a/test/Transforms/InstMerge/st_sink_no_barrier_call.ll b/test/Transforms/InstMerge/st_sink_no_barrier_call.ll new file mode 100644 index 000000000000..72f1fdf77371 --- /dev/null +++ b/test/Transforms/InstMerge/st_sink_no_barrier_call.ll @@ -0,0 +1,45 @@ +; Test to make sure that stores in a diamond get merged with a non barrier function call after the store instruction +; Stores sunks into the footer. +; RUN: opt -basicaa -memdep -mldst-motion -S < %s | FileCheck %s +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + +%struct.node = type { i32, %struct.node*, %struct.node*, %struct.node*, i32, i32, i32, i32 } + +declare i32 @foo(i32 %x) #0 + +; Function Attrs: nounwind uwtable +define void @sink_store(%struct.node* nocapture %r, i32 %index) { +entry: + %node.0.in16 = getelementptr inbounds %struct.node* %r, i64 0, i32 2 + %node.017 = load %struct.node** %node.0.in16, align 8 + %index.addr = alloca i32, align 4 + store i32 %index, i32* %index.addr, align 4 + %0 = load i32* %index.addr, align 4 + %cmp = icmp slt i32 %0, 0 + br i1 %cmp, label %if.then, label %if.else + +; CHECK: if.then +if.then: ; preds = %entry + %1 = load i32* %index.addr, align 4 + %p1 = getelementptr inbounds %struct.node* %node.017, i32 0, i32 6 + ; CHECK-NOT: store i32 + store i32 %1, i32* %p1, align 4 + br label %if.end + +; CHECK: if.else +if.else: ; preds = %entry + %2 = load i32* %index.addr, align 4 + %add = add nsw i32 %2, 1 + %p3 = getelementptr inbounds %struct.node* %node.017, i32 0, i32 6 + ; CHECK-NOT: store i32 + store i32 %add, i32* %p3, align 4 + call i32 @foo(i32 5) ;not a barrier + br label %if.end + +; CHECK: if.end +if.end: ; preds = %if.else, %if.then +; CHECK: store + ret void +} + +attributes #0 = { readnone } diff --git a/test/Transforms/InstMerge/st_sink_no_barrier_load.ll b/test/Transforms/InstMerge/st_sink_no_barrier_load.ll new file mode 100644 index 000000000000..5be0c254ba6f --- /dev/null +++ b/test/Transforms/InstMerge/st_sink_no_barrier_load.ll @@ -0,0 +1,43 @@ +; Test to make sure that stores in a diamond get merged with a non barrier load after the store instruction +; Stores sunks into the footer. +; RUN: opt -basicaa -memdep -mldst-motion -S < %s | FileCheck %s +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + +%struct.node = type { i32, %struct.node*, %struct.node*, %struct.node*, i32, i32, i32, i32 } + +; Function Attrs: nounwind uwtable +define void @sink_store(%struct.node* nocapture %r, i32 %index) { +entry: + %node.0.in16 = getelementptr inbounds %struct.node* %r, i64 0, i32 2 + %node.017 = load %struct.node** %node.0.in16, align 8 + %index.addr = alloca i32, align 4 + store i32 %index, i32* %index.addr, align 4 + %0 = load i32* %index.addr, align 4 + %cmp = icmp slt i32 %0, 0 + br i1 %cmp, label %if.then, label %if.else + +; CHECK: if.then +if.then: ; preds = %entry + %1 = load i32* %index.addr, align 4 + %p1 = getelementptr inbounds %struct.node* %node.017, i32 0, i32 6 + ; CHECK-NOT: store i32 + store i32 %1, i32* %p1, align 4 + %p2 = getelementptr inbounds %struct.node* %node.017, i32 5, i32 6 + ; CHECK: load i32* + %not_barrier = load i32 * %p2, align 4 + br label %if.end + +; CHECK: if.else +if.else: ; preds = %entry + %2 = load i32* %index.addr, align 4 + %add = add nsw i32 %2, 1 + %p3 = getelementptr inbounds %struct.node* %node.017, i32 0, i32 6 + ; CHECK-NOT: store i32 + store i32 %add, i32* %p3, align 4 + br label %if.end + +; CHECK: if.end +if.end: ; preds = %if.else, %if.then +; CHECK: store + ret void +} diff --git a/test/Transforms/InstMerge/st_sink_no_barrier_store.ll b/test/Transforms/InstMerge/st_sink_no_barrier_store.ll new file mode 100644 index 000000000000..06e2b63ca3ed --- /dev/null +++ b/test/Transforms/InstMerge/st_sink_no_barrier_store.ll @@ -0,0 +1,42 @@ +; Test to make sure that stores in a diamond get merged with a non barrier store after the store instruction to be sunk +; Stores sunks into the footer. +; RUN: opt -basicaa -memdep -mldst-motion -S < %s | FileCheck %s +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + +%struct.node = type { i32, %struct.node*, %struct.node*, %struct.node*, i32, i32, i32, i32 } + +; Function Attrs: nounwind uwtable +define void @sink_store(%struct.node* nocapture %r, i32 %index) { +entry: + %node.0.in16 = getelementptr inbounds %struct.node* %r, i64 0, i32 2 + %node.017 = load %struct.node** %node.0.in16, align 8 + %index.addr = alloca i32, align 4 + store i32 %index, i32* %index.addr, align 4 + %0 = load i32* %index.addr, align 4 + %cmp = icmp slt i32 %0, 0 + br i1 %cmp, label %if.then, label %if.else + +; CHECK: if.then +if.then: ; preds = %entry + %1 = load i32* %index.addr, align 4 + %p1 = getelementptr inbounds %struct.node* %node.017, i32 0, i32 6 + ; CHECK-NOT: store i32 + store i32 %1, i32* %p1, align 4 + br label %if.end + +; CHECK: if.else +if.else: ; preds = %entry + %2 = load i32* %index.addr, align 4 + %add = add nsw i32 %2, 1 + %p2 = getelementptr inbounds %struct.node* %node.017, i32 0, i32 6 + store i32 %add, i32* %p2, align 4 + %p3 = getelementptr inbounds %struct.node* %node.017, i32 5, i32 6 + ; CHECK: store i32 + store i32 %add, i32* %p3, align 4 ; This is not a barrier + br label %if.end + +; CHECK: if.end +if.end: ; preds = %if.else, %if.then +; CHECK: store + ret void +} diff --git a/test/Transforms/InstMerge/st_sink_two_stores.ll b/test/Transforms/InstMerge/st_sink_two_stores.ll new file mode 100644 index 000000000000..1f7c6aa478ba --- /dev/null +++ b/test/Transforms/InstMerge/st_sink_two_stores.ll @@ -0,0 +1,47 @@ +; Test to make sure that stores in a diamond get merged +; Stores sunks into the footer. +; RUN: opt -basicaa -memdep -mldst-motion -S < %s | FileCheck %s +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + +%struct.node = type { i32, %struct.node*, %struct.node*, %struct.node*, i32, i32, i32, i32 } + +; Function Attrs: nounwind uwtable +define void @sink_store(%struct.node* nocapture %r, i32 %index) { +entry: + %node.0.in16 = getelementptr inbounds %struct.node* %r, i64 0, i32 2 + %node.017 = load %struct.node** %node.0.in16, align 8 + %index.addr = alloca i32, align 4 + store i32 %index, i32* %index.addr, align 4 + %0 = load i32* %index.addr, align 4 + %cmp = icmp slt i32 %0, 0 + br i1 %cmp, label %if.then, label %if.else + +; CHECK: if.then +if.then: ; preds = %entry + %1 = load i32* %index.addr, align 4 + %p1 = getelementptr inbounds %struct.node* %node.017, i32 0, i32 6 + ; CHECK-NOT: store i32 + store i32 %1, i32* %p1, align 4 + %p2 = getelementptr inbounds %struct.node* %node.017, i32 4, i32 6 + ; CHECK-NOT: store i32 + store i32 %1, i32* %p2, align 4 + br label %if.end + +; CHECK: if.else +if.else: ; preds = %entry + %2 = load i32* %index.addr, align 4 + %add = add nsw i32 %2, 1 + %p3 = getelementptr inbounds %struct.node* %node.017, i32 0, i32 6 + ; CHECK-NOT: store i32 + store i32 %add, i32* %p3, align 4 + %p4 = getelementptr inbounds %struct.node* %node.017, i32 4, i32 6 + ; CHECK-NOT: store i32 + store i32 %2, i32* %p4, align 4 + br label %if.end + +; CHECK: if.end +if.end: ; preds = %if.else, %if.then +; CHECK: store +; CHECK: store + ret void +} diff --git a/test/Transforms/InstMerge/st_sink_with_barrier.ll b/test/Transforms/InstMerge/st_sink_with_barrier.ll new file mode 100644 index 000000000000..d4efaa7efff7 --- /dev/null +++ b/test/Transforms/InstMerge/st_sink_with_barrier.ll @@ -0,0 +1,42 @@ +; Test to make sure that load from the same address as a store and appears after the store prevents the store from being sunk +; RUN: opt -basicaa -memdep -mldst-motion -S < %s | FileCheck %s +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + +%struct.node = type { i32, %struct.node*, %struct.node*, %struct.node*, i32, i32, i32, i32 } + +; Function Attrs: nounwind uwtable +define void @sink_store(%struct.node* nocapture %r, i32 %index) { +entry: + %node.0.in16 = getelementptr inbounds %struct.node* %r, i64 0, i32 2 + %node.017 = load %struct.node** %node.0.in16, align 8 + %index.addr = alloca i32, align 4 + store i32 %index, i32* %index.addr, align 4 + %0 = load i32* %index.addr, align 4 + %cmp = icmp slt i32 %0, 0 + br i1 %cmp, label %if.then, label %if.else + +; CHECK: if.then +if.then: ; preds = %entry + %1 = load i32* %index.addr, align 4 + %p1 = getelementptr inbounds %struct.node* %node.017, i32 0, i32 6 + ; CHECK: store i32 + store i32 %1, i32* %p1, align 4 + %p2 = getelementptr inbounds %struct.node* %node.017, i32 0, i32 6 + ; CHECK: load i32* + %barrier = load i32 * %p2, align 4 + br label %if.end + +; CHECK: if.else +if.else: ; preds = %entry + %2 = load i32* %index.addr, align 4 + %add = add nsw i32 %2, 1 + %p3 = getelementptr inbounds %struct.node* %node.017, i32 0, i32 6 + ; CHECK: store i32 + store i32 %add, i32* %p3, align 4 + br label %if.end + +; CHECK: if.end +if.end: ; preds = %if.else, %if.then +; CHECK-NOT: store + ret void +} diff --git a/test/Transforms/InstSimplify/AndOrXor.ll b/test/Transforms/InstSimplify/AndOrXor.ll index c59d6c916a6b..ce3c2aa6af22 100644 --- a/test/Transforms/InstSimplify/AndOrXor.ll +++ b/test/Transforms/InstSimplify/AndOrXor.ll @@ -20,3 +20,186 @@ define i64 @pow2b(i32 %x) { ret i64 %e2 ; CHECK: ret i64 %e } + +define i32 @sub_neg_nuw(i32 %x, i32 %y) { +; CHECK-LABEL: @sub_neg_nuw( + %neg = sub nuw i32 0, %y + %sub = sub i32 %x, %neg + ret i32 %sub +; CHECK: ret i32 %x +} + +define i1 @and_of_icmps0(i32 %b) { +; CHECK-LABEL: @and_of_icmps0( + %1 = add i32 %b, 2 + %2 = icmp ult i32 %1, 4 + %cmp3 = icmp sgt i32 %b, 2 + %cmp = and i1 %2, %cmp3 + ret i1 %cmp +; CHECK: ret i1 false +} + +define i1 @and_of_icmps1(i32 %b) { +; CHECK-LABEL: @and_of_icmps1( + %1 = add nsw i32 %b, 2 + %2 = icmp slt i32 %1, 4 + %cmp3 = icmp sgt i32 %b, 2 + %cmp = and i1 %2, %cmp3 + ret i1 %cmp +; CHECK: ret i1 false +} + +define i1 @and_of_icmps2(i32 %b) { +; CHECK-LABEL: @and_of_icmps2( + %1 = add i32 %b, 2 + %2 = icmp ule i32 %1, 3 + %cmp3 = icmp sgt i32 %b, 2 + %cmp = and i1 %2, %cmp3 + ret i1 %cmp +; CHECK: ret i1 false +} + +define i1 @and_of_icmps3(i32 %b) { +; CHECK-LABEL: @and_of_icmps3( + %1 = add nsw i32 %b, 2 + %2 = icmp sle i32 %1, 3 + %cmp3 = icmp sgt i32 %b, 2 + %cmp = and i1 %2, %cmp3 + ret i1 %cmp +; CHECK: ret i1 false +} + +define i1 @and_of_icmps4(i32 %b) { +; CHECK-LABEL: @and_of_icmps4( + %1 = add nuw i32 %b, 2 + %2 = icmp ult i32 %1, 4 + %cmp3 = icmp ugt i32 %b, 2 + %cmp = and i1 %2, %cmp3 + ret i1 %cmp +; CHECK: ret i1 false +} + +define i1 @and_of_icmps5(i32 %b) { +; CHECK-LABEL: @and_of_icmps5( + %1 = add nuw i32 %b, 2 + %2 = icmp ule i32 %1, 3 + %cmp3 = icmp ugt i32 %b, 2 + %cmp = and i1 %2, %cmp3 + ret i1 %cmp +; CHECK: ret i1 false +} + +define i1 @or_of_icmps0(i32 %b) { +; CHECK-LABEL: @or_of_icmps0( + %1 = add i32 %b, 2 + %2 = icmp uge i32 %1, 4 + %cmp3 = icmp sle i32 %b, 2 + %cmp = or i1 %2, %cmp3 + ret i1 %cmp +; CHECK: ret i1 true +} + +define i1 @or_of_icmps1(i32 %b) { +; CHECK-LABEL: @or_of_icmps1( + %1 = add nsw i32 %b, 2 + %2 = icmp sge i32 %1, 4 + %cmp3 = icmp sle i32 %b, 2 + %cmp = or i1 %2, %cmp3 + ret i1 %cmp +; CHECK: ret i1 true +} + +define i1 @or_of_icmps2(i32 %b) { +; CHECK-LABEL: @or_of_icmps2( + %1 = add i32 %b, 2 + %2 = icmp ugt i32 %1, 3 + %cmp3 = icmp sle i32 %b, 2 + %cmp = or i1 %2, %cmp3 + ret i1 %cmp +; CHECK: ret i1 true +} + +define i1 @or_of_icmps3(i32 %b) { +; CHECK-LABEL: @or_of_icmps3( + %1 = add nsw i32 %b, 2 + %2 = icmp sgt i32 %1, 3 + %cmp3 = icmp sle i32 %b, 2 + %cmp = or i1 %2, %cmp3 + ret i1 %cmp +; CHECK: ret i1 true +} + +define i1 @or_of_icmps4(i32 %b) { +; CHECK-LABEL: @or_of_icmps4( + %1 = add nuw i32 %b, 2 + %2 = icmp uge i32 %1, 4 + %cmp3 = icmp ule i32 %b, 2 + %cmp = or i1 %2, %cmp3 + ret i1 %cmp +; CHECK: ret i1 true +} + +define i1 @or_of_icmps5(i32 %b) { +; CHECK-LABEL: @or_of_icmps5( + %1 = add nuw i32 %b, 2 + %2 = icmp ugt i32 %1, 3 + %cmp3 = icmp ule i32 %b, 2 + %cmp = or i1 %2, %cmp3 + ret i1 %cmp +; CHECK: ret i1 true +} + +define i32 @neg_nuw(i32 %x) { +; CHECK-LABEL: @neg_nuw( + %neg = sub nuw i32 0, %x + ret i32 %neg +; CHECK: ret i32 0 +} + +define i1 @and_icmp1(i32 %x, i32 %y) { + %1 = icmp ult i32 %x, %y + %2 = icmp ne i32 %y, 0 + %3 = and i1 %1, %2 + ret i1 %3 +} +; CHECK-LABEL: @and_icmp1( +; CHECK: %[[cmp:.*]] = icmp ult i32 %x, %y +; CHECK: ret i1 %[[cmp]] + +define i1 @and_icmp2(i32 %x, i32 %y) { + %1 = icmp ult i32 %x, %y + %2 = icmp eq i32 %y, 0 + %3 = and i1 %1, %2 + ret i1 %3 +} +; CHECK-LABEL: @and_icmp2( +; CHECK: ret i1 false + +define i1 @or_icmp1(i32 %x, i32 %y) { + %1 = icmp ult i32 %x, %y + %2 = icmp ne i32 %y, 0 + %3 = or i1 %1, %2 + ret i1 %3 +} +; CHECK-LABEL: @or_icmp1( +; CHECK: %[[cmp:.*]] = icmp ne i32 %y, 0 +; CHECK: ret i1 %[[cmp]] + +define i1 @or_icmp2(i32 %x, i32 %y) { + %1 = icmp uge i32 %x, %y + %2 = icmp ne i32 %y, 0 + %3 = or i1 %1, %2 + ret i1 %3 +} +; CHECK-LABEL: @or_icmp2( +; CHECK: ret i1 true + +define i1 @or_icmp3(i32 %x, i32 %y) { + %1 = icmp uge i32 %x, %y + %2 = icmp eq i32 %y, 0 + %3 = or i1 %1, %2 + ret i1 %3 +} +; CHECK-LABEL: @or_icmp3( +; CHECK: %[[cmp:.*]] = icmp uge i32 %x, %y +; CHECK: ret i1 %[[cmp]] diff --git a/test/Transforms/InstSimplify/ashr-nop.ll b/test/Transforms/InstSimplify/ashr-nop.ll deleted file mode 100644 index 0914d725e40d..000000000000 --- a/test/Transforms/InstSimplify/ashr-nop.ll +++ /dev/null @@ -1,10 +0,0 @@ -; RUN: opt < %s -instsimplify -S | FileCheck %s - -; CHECK-LABEL: @foo -; CHECK-NOT: ashr -define i32 @foo(i32 %x) { - %o = and i32 %x, 1 - %n = add i32 %o, -1 - %t = ashr i32 %n, 17 - ret i32 %t -} diff --git a/test/Transforms/InstSimplify/assume.ll b/test/Transforms/InstSimplify/assume.ll new file mode 100644 index 000000000000..4dd0a8f4a82d --- /dev/null +++ b/test/Transforms/InstSimplify/assume.ll @@ -0,0 +1,13 @@ +; RUN: opt -instsimplify -S < %s | FileCheck %s + +define void @test1() { + call void @llvm.assume(i1 1) + ret void + +; CHECK-LABEL: @test1 +; CHECK-NOT: llvm.assume +; CHECK: ret void +} + +declare void @llvm.assume(i1) nounwind + diff --git a/test/Transforms/InstSimplify/compare.ll b/test/Transforms/InstSimplify/compare.ll index 94872d35bb97..10c7ca6754e3 100644 --- a/test/Transforms/InstSimplify/compare.ll +++ b/test/Transforms/InstSimplify/compare.ll @@ -333,14 +333,46 @@ define i1 @or(i32 %x) { ; CHECK: ret i1 false } -define i1 @shl(i32 %x) { -; CHECK-LABEL: @shl( +define i1 @shl1(i32 %x) { +; CHECK-LABEL: @shl1( %s = shl i32 1, %x %c = icmp eq i32 %s, 0 ret i1 %c ; CHECK: ret i1 false } +define i1 @shl2(i32 %X) { +; CHECK: @shl2 + %sub = shl nsw i32 -1, %X + %cmp = icmp eq i32 %sub, 31 + ret i1 %cmp +; CHECK-NEXT: ret i1 false +} + +define i1 @shl3(i32 %X) { +; CHECK: @shl3 + %sub = shl nuw i32 4, %X + %cmp = icmp eq i32 %sub, 31 + ret i1 %cmp +; CHECK-NEXT: ret i1 false +} + +define i1 @shl4(i32 %X) { +; CHECK: @shl4 + %sub = shl nsw i32 -1, %X + %cmp = icmp sle i32 %sub, -1 + ret i1 %cmp +; CHECK-NEXT: ret i1 true +} + +define i1 @shl5(i32 %X) { +; CHECK: @shl5 + %sub = shl nuw i32 4, %X + %cmp = icmp ugt i32 %sub, 3 + ret i1 %cmp +; CHECK-NEXT: ret i1 true +} + define i1 @lshr1(i32 %x) { ; CHECK-LABEL: @lshr1( %s = lshr i32 -1, %x @@ -917,6 +949,29 @@ define i1 @returns_nonnull_as_deref() { ; CHECK: ret } +define i1 @nonnull_load(i32** %addr) { + %ptr = load i32** %addr, !nonnull !{} + %cmp = icmp eq i32* %ptr, null + ret i1 %cmp +; CHECK-LABEL: @nonnull_load +; CHECK: ret i1 false +} + +define i1 @nonnull_load_as_outer(i32* addrspace(1)* %addr) { + %ptr = load i32* addrspace(1)* %addr, !nonnull !{} + %cmp = icmp eq i32* %ptr, null + ret i1 %cmp +; CHECK-LABEL: @nonnull_load_as_outer +; CHECK: ret i1 false +} +define i1 @nonnull_load_as_inner(i32 addrspace(1)** %addr) { + %ptr = load i32 addrspace(1)** %addr, !nonnull !{} + %cmp = icmp eq i32 addrspace(1)* %ptr, null + ret i1 %cmp +; CHECK-LABEL: @nonnull_load_as_inner +; CHECK: ret i1 false +} + ; If a bit is known to be zero for A and known to be one for B, ; then A and B cannot be equal. define i1 @icmp_eq_const(i32 %a) nounwind { @@ -969,3 +1024,143 @@ define i1 @icmp_sdiv_neg1(i64 %a) { ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[DIV]], 1073741824 ; CHECK-NEXT: ret i1 [[CMP]] } + +define i1 @icmp_known_bits(i4 %x, i4 %y) { + %and1 = and i4 %y, -7 + %and2 = and i4 %x, -7 + %or1 = or i4 %and1, 2 + %or2 = or i4 %and2, 2 + %add = add i4 %or1, %or2 + %cmp = icmp eq i4 %add, 0 + ret i1 %cmp + +; CHECK-LABEL: @icmp_known_bits +; CHECK-NEXT: ret i1 false +} + +define i1 @icmp_shl_nuw_1(i64 %a) { + %shl = shl nuw i64 1, %a + %cmp = icmp ne i64 %shl, 0 + ret i1 %cmp + +; CHECK-LABEL: @icmp_shl_nuw_1 +; CHECK-NEXT: ret i1 true +} + +define i1 @icmp_shl_nsw_neg1(i64 %a) { + %shl = shl nsw i64 -1, %a + %cmp = icmp sge i64 %shl, 3 + ret i1 %cmp + +; CHECK-LABEL: @icmp_shl_nsw_neg1 +; CHECK-NEXT: ret i1 false +} + +define i1 @icmp_shl_nsw_1(i64 %a) { + %shl = shl nsw i64 1, %a + %cmp = icmp sge i64 %shl, 0 + ret i1 %cmp + +; CHECK-LABEL: @icmp_shl_nsw_1 +; CHECK-NEXT: ret i1 true +} + +define i1 @icmp_shl_1_V_ugt_2147483648(i32 %V) { + %shl = shl i32 1, %V + %cmp = icmp ugt i32 %shl, 2147483648 + ret i1 %cmp + +; CHECK-LABEL: @icmp_shl_1_V_ugt_2147483648( +; CHECK-NEXT: ret i1 false +} + +define i1 @icmp_shl_1_V_ule_2147483648(i32 %V) { + %shl = shl i32 1, %V + %cmp = icmp ule i32 %shl, 2147483648 + ret i1 %cmp + +; CHECK-LABEL: @icmp_shl_1_V_ule_2147483648( +; CHECK-NEXT: ret i1 true +} + +define i1 @icmp_shl_1_V_eq_31(i32 %V) { + %shl = shl i32 1, %V + %cmp = icmp eq i32 %shl, 31 + ret i1 %cmp + +; CHECK-LABEL: @icmp_shl_1_V_eq_31( +; CHECK-NEXT: ret i1 false +} + +define i1 @icmp_shl_1_V_ne_31(i32 %V) { + %shl = shl i32 1, %V + %cmp = icmp ne i32 %shl, 31 + ret i1 %cmp + +; CHECK-LABEL: @icmp_shl_1_V_ne_31( +; CHECK-NEXT: ret i1 true +} + +define i1 @tautological1(i32 %A, i32 %B) { + %C = and i32 %A, %B + %D = icmp ugt i32 %C, %A + ret i1 %D +; CHECK-LABEL: @tautological1( +; CHECK: ret i1 false +} + +define i1 @tautological2(i32 %A, i32 %B) { + %C = and i32 %A, %B + %D = icmp ule i32 %C, %A + ret i1 %D +; CHECK-LABEL: @tautological2( +; CHECK: ret i1 true +} + +define i1 @tautological3(i32 %A, i32 %B) { + %C = or i32 %A, %B + %D = icmp ule i32 %A, %C + ret i1 %D +; CHECK-LABEL: @tautological3( +; CHECK: ret i1 true +} + +define i1 @tautological4(i32 %A, i32 %B) { + %C = or i32 %A, %B + %D = icmp ugt i32 %A, %C + ret i1 %D +; CHECK-LABEL: @tautological4( +; CHECK: ret i1 false +} + +define i1 @tautological5(i32 %A, i32 %B) { + %C = or i32 %A, %B + %D = icmp ult i32 %C, %A + ret i1 %D +; CHECK-LABEL: @tautological5( +; CHECK: ret i1 false +} + +define i1 @tautological6(i32 %A, i32 %B) { + %C = or i32 %A, %B + %D = icmp uge i32 %C, %A + ret i1 %D +; CHECK-LABEL: @tautological6( +; CHECK: ret i1 true +} + +define i1 @tautological7(i32 %A, i32 %B) { + %C = and i32 %A, %B + %D = icmp uge i32 %A, %C + ret i1 %D +; CHECK-LABEL: @tautological7( +; CHECK: ret i1 true +} + +define i1 @tautological8(i32 %A, i32 %B) { + %C = and i32 %A, %B + %D = icmp ult i32 %A, %C + ret i1 %D +; CHECK-LABEL: @tautological8( +; CHECK: ret i1 false +} diff --git a/test/Transforms/InstSimplify/exact-nsw-nuw.ll b/test/Transforms/InstSimplify/exact-nsw-nuw.ll index a0e326b13c02..5ccc8083e645 100644 --- a/test/Transforms/InstSimplify/exact-nsw-nuw.ll +++ b/test/Transforms/InstSimplify/exact-nsw-nuw.ll @@ -42,3 +42,19 @@ define i32 @shift5(i32 %A, i32 %B) { %D = ashr i32 %C, %B ret i32 %D } + +; CHECK-LABEL: @div1( +; CHECK: ret i32 0 +define i32 @div1(i32 %V) { + %A = udiv i32 %V, -2147483648 + %B = udiv i32 %A, -2147483648 + ret i32 %B +} + +; CHECK-LABEL: @div2( +; CHECK-NOT: ret i32 0 +define i32 @div2(i32 %V) { + %A = sdiv i32 %V, -1 + %B = sdiv i32 %A, -2147483648 + ret i32 %B +} diff --git a/test/Transforms/InstSimplify/fold-builtin-fma.ll b/test/Transforms/InstSimplify/fold-builtin-fma.ll new file mode 100644 index 000000000000..6331b8c2dd43 --- /dev/null +++ b/test/Transforms/InstSimplify/fold-builtin-fma.ll @@ -0,0 +1,119 @@ +; RUN: opt -instsimplify -S < %s | FileCheck %s + +; Fixes PR20832 +; Make sure that we correctly fold a fused multiply-add where operands +; are all finite constants and addend is zero. + +declare double @llvm.fma.f64(double, double, double) + + +define double @PR20832() { + %1 = call double @llvm.fma.f64(double 7.0, double 8.0, double 0.0) + ret double %1 +} +; CHECK-LABEL: @PR20832( +; CHECK: ret double 5.600000e+01 + +; Test builtin fma with all finite non-zero constants. +define double @test_all_finite() { + %1 = call double @llvm.fma.f64(double 7.0, double 8.0, double 5.0) + ret double %1 +} +; CHECK-LABEL: @test_all_finite( +; CHECK: ret double 6.100000e+01 + +; Test builtin fma with a +/-NaN addend. +define double @test_NaN_addend() { + %1 = call double @llvm.fma.f64(double 7.0, double 8.0, double 0x7FF8000000000000) + ret double %1 +} +; CHECK-LABEL: @test_NaN_addend( +; CHECK: ret double 0x7FF8000000000000 + +define double @test_NaN_addend_2() { + %1 = call double @llvm.fma.f64(double 7.0, double 8.0, double 0xFFF8000000000000) + ret double %1 +} +; CHECK-LABEL: @test_NaN_addend_2( +; CHECK: ret double 0xFFF8000000000000 + +; Test builtin fma with a +/-Inf addend. +define double @test_Inf_addend() { + %1 = call double @llvm.fma.f64(double 7.0, double 8.0, double 0x7FF0000000000000) + ret double %1 +} +; CHECK-LABEL: @test_Inf_addend( +; CHECK: ret double 0x7FF0000000000000 + +define double @test_Inf_addend_2() { + %1 = call double @llvm.fma.f64(double 7.0, double 8.0, double 0xFFF0000000000000) + ret double %1 +} +; CHECK-LABEL: @test_Inf_addend_2( +; CHECK: ret double 0xFFF0000000000000 + +; Test builtin fma with one of the operands to the multiply being +/-NaN. +define double @test_NaN_1() { + %1 = call double @llvm.fma.f64(double 0x7FF8000000000000, double 8.0, double 0.0) + ret double %1 +} +; CHECK-LABEL: @test_NaN_1( +; CHECK: ret double 0x7FF8000000000000 + + +define double @test_NaN_2() { + %1 = call double @llvm.fma.f64(double 7.0, double 0x7FF8000000000000, double 0.0) + ret double %1 +} +; CHECK-LABEL: @test_NaN_2( +; CHECK: ret double 0x7FF8000000000000 + + +define double @test_NaN_3() { + %1 = call double @llvm.fma.f64(double 0xFFF8000000000000, double 8.0, double 0.0) + ret double %1 +} +; CHECK-LABEL: @test_NaN_3( +; CHECK: ret double 0x7FF8000000000000 + + +define double @test_NaN_4() { + %1 = call double @llvm.fma.f64(double 7.0, double 0xFFF8000000000000, double 0.0) + ret double %1 +} +; CHECK-LABEL: @test_NaN_4( +; CHECK: ret double 0x7FF8000000000000 + + +; Test builtin fma with one of the operands to the multiply being +/-Inf. +define double @test_Inf_1() { + %1 = call double @llvm.fma.f64(double 0x7FF0000000000000, double 8.0, double 0.0) + ret double %1 +} +; CHECK-LABEL: @test_Inf_1( +; CHECK: ret double 0x7FF0000000000000 + + +define double @test_Inf_2() { + %1 = call double @llvm.fma.f64(double 7.0, double 0x7FF0000000000000, double 0.0) + ret double %1 +} +; CHECK-LABEL: @test_Inf_2( +; CHECK: ret double 0x7FF0000000000000 + + +define double @test_Inf_3() { + %1 = call double @llvm.fma.f64(double 0xFFF0000000000000, double 8.0, double 0.0) + ret double %1 +} +; CHECK-LABEL: @test_Inf_3( +; CHECK: ret double 0xFFF0000000000000 + + +define double @test_Inf_4() { + %1 = call double @llvm.fma.f64(double 7.0, double 0xFFF0000000000000, double 0.0) + ret double %1 +} +; CHECK-LABEL: @test_Inf_4( +; CHECK: ret double 0xFFF0000000000000 + diff --git a/test/Transforms/InstSimplify/gep.ll b/test/Transforms/InstSimplify/gep.ll new file mode 100644 index 000000000000..49a97f133cef --- /dev/null +++ b/test/Transforms/InstSimplify/gep.ll @@ -0,0 +1,80 @@ +; RUN: opt -S -instsimplify < %s | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +%struct.A = type { [7 x i8] } + +define %struct.A* @test1(%struct.A* %b, %struct.A* %e) { + %e_ptr = ptrtoint %struct.A* %e to i64 + %b_ptr = ptrtoint %struct.A* %b to i64 + %sub = sub i64 %e_ptr, %b_ptr + %sdiv = sdiv exact i64 %sub, 7 + %gep = getelementptr inbounds %struct.A* %b, i64 %sdiv + ret %struct.A* %gep +; CHECK-LABEL: @test1 +; CHECK-NEXT: ret %struct.A* %e +} + +define i8* @test2(i8* %b, i8* %e) { + %e_ptr = ptrtoint i8* %e to i64 + %b_ptr = ptrtoint i8* %b to i64 + %sub = sub i64 %e_ptr, %b_ptr + %gep = getelementptr inbounds i8* %b, i64 %sub + ret i8* %gep +; CHECK-LABEL: @test2 +; CHECK-NEXT: ret i8* %e +} + +define i64* @test3(i64* %b, i64* %e) { + %e_ptr = ptrtoint i64* %e to i64 + %b_ptr = ptrtoint i64* %b to i64 + %sub = sub i64 %e_ptr, %b_ptr + %ashr = ashr exact i64 %sub, 3 + %gep = getelementptr inbounds i64* %b, i64 %ashr + ret i64* %gep +; CHECK-LABEL: @test3 +; CHECK-NEXT: ret i64* %e +} + +define %struct.A* @test4(%struct.A* %b) { + %b_ptr = ptrtoint %struct.A* %b to i64 + %sub = sub i64 0, %b_ptr + %sdiv = sdiv exact i64 %sub, 7 + %gep = getelementptr inbounds %struct.A* %b, i64 %sdiv + ret %struct.A* %gep +; CHECK-LABEL: @test4 +; CHECK-NEXT: ret %struct.A* null +} + +define i8* @test5(i8* %b) { + %b_ptr = ptrtoint i8* %b to i64 + %sub = sub i64 0, %b_ptr + %gep = getelementptr inbounds i8* %b, i64 %sub + ret i8* %gep +; CHECK-LABEL: @test5 +; CHECK-NEXT: ret i8* null +} + +define i64* @test6(i64* %b) { + %b_ptr = ptrtoint i64* %b to i64 + %sub = sub i64 0, %b_ptr + %ashr = ashr exact i64 %sub, 3 + %gep = getelementptr inbounds i64* %b, i64 %ashr + ret i64* %gep +; CHECK-LABEL: @test6 +; CHECK-NEXT: ret i64* null +} + +define i8* @test7(i8* %b, i8** %e) { + %e_ptr = ptrtoint i8** %e to i64 + %b_ptr = ptrtoint i8* %b to i64 + %sub = sub i64 %e_ptr, %b_ptr + %gep = getelementptr inbounds i8* %b, i64 %sub + ret i8* %gep +; CHECK-LABEL: @test7 +; CHECK-NEXT: ptrtoint +; CHECK-NEXT: ptrtoint +; CHECK-NEXT: sub +; CHECK-NEXT: getelementptr +; CHECK-NEXT: ret +} diff --git a/test/Transforms/InstSimplify/noalias-ptr.ll b/test/Transforms/InstSimplify/noalias-ptr.ll new file mode 100644 index 000000000000..7693e5542355 --- /dev/null +++ b/test/Transforms/InstSimplify/noalias-ptr.ll @@ -0,0 +1,259 @@ +; RUN: opt -instsimplify -S < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@g1 = global i32 0, align 4 +@g2 = internal global i32 0, align 4 +@g3 = unnamed_addr global i32 0, align 4 +@g4 = hidden global i32 0, align 4 +@g5 = protected global i32 0, align 4 +@g6 = thread_local unnamed_addr global i32 0, align 4 + +; Make sure we can simplify away a pointer comparison between +; dynamically-allocated memory and a local stack allocation. +; void p() +; { +; int *mData; +; int mStackData[10]; +; mData = new int[12]; +; if (mData != mStackData) { +; delete[] mData; +; } +; } + +define void @_Z2p1v() #0 { + %mStackData = alloca [10 x i32], align 16 + %1 = bitcast [10 x i32]* %mStackData to i8* + %2 = tail call noalias i8* @_Znam(i64 48) #4 + %3 = bitcast i8* %2 to i32* + %4 = getelementptr inbounds [10 x i32]* %mStackData, i64 0, i64 0 + %5 = icmp eq i32* %3, %4 + br i1 %5, label %7, label %6 + +; CHECK-LABEL: @_Z2p1v +; CHECK-NOT: icmp +; CHECK: ret void + +; <label>:6 ; preds = %0 + call void @_ZdaPv(i8* %2) #5 + br label %7 + +; <label>:7 ; preds = %0, %6 + ret void +} + +; Also check a more-complicated case with multiple underlying objects. + +define void @_Z2p2bb(i1 zeroext %b1, i1 zeroext %b2) #0 { + %mStackData = alloca [10 x i32], align 16 + %1 = bitcast [10 x i32]* %mStackData to i8* + %2 = getelementptr inbounds [10 x i32]* %mStackData, i64 0, i64 0 + %3 = select i1 %b1, i32* %2, i32* @g2 + %4 = tail call noalias i8* @_Znam(i64 48) #4 + %5 = tail call noalias i8* @_Znam(i64 48) #4 + %.v = select i1 %b2, i8* %4, i8* %5 + %6 = bitcast i8* %.v to i32* + %7 = icmp eq i32* %6, %3 + br i1 %7, label %9, label %8 + +; CHECK-LABEL: @_Z2p2bb +; CHECK-NOT: icmp +; CHECK: ret void + +; <label>:8 ; preds = %0 + call void @_ZdaPv(i8* %4) #5 + call void @_ZdaPv(i8* %5) #5 + br label %9 + +; <label>:9 ; preds = %0, %8 + ret void +} + +define void @_Z2p4bb(i1 zeroext %b1, i1 zeroext %b2) #0 { + %mStackData = alloca [10 x i32], align 16 + %1 = bitcast [10 x i32]* %mStackData to i8* + %2 = getelementptr inbounds [10 x i32]* %mStackData, i64 0, i64 0 + %3 = select i1 %b1, i32* %2, i32* @g3 + %4 = tail call noalias i8* @_Znam(i64 48) #4 + %5 = tail call noalias i8* @_Znam(i64 48) #4 + %.v = select i1 %b2, i8* %4, i8* %5 + %6 = bitcast i8* %.v to i32* + %7 = icmp eq i32* %6, %3 + br i1 %7, label %9, label %8 + +; CHECK-LABEL: @_Z2p4bb +; CHECK-NOT: icmp +; CHECK: ret void + +; <label>:8 ; preds = %0 + call void @_ZdaPv(i8* %4) #5 + call void @_ZdaPv(i8* %5) #5 + br label %9 + +; <label>:9 ; preds = %0, %8 + ret void +} + +define void @_Z2p5bb(i1 zeroext %b1, i1 zeroext %b2) #0 { + %mStackData = alloca [10 x i32], align 16 + %1 = bitcast [10 x i32]* %mStackData to i8* + %2 = getelementptr inbounds [10 x i32]* %mStackData, i64 0, i64 0 + %3 = select i1 %b1, i32* %2, i32* @g4 + %4 = tail call noalias i8* @_Znam(i64 48) #4 + %5 = tail call noalias i8* @_Znam(i64 48) #4 + %.v = select i1 %b2, i8* %4, i8* %5 + %6 = bitcast i8* %.v to i32* + %7 = icmp eq i32* %6, %3 + br i1 %7, label %9, label %8 + +; CHECK-LABEL: @_Z2p5bb +; CHECK-NOT: icmp +; CHECK: ret void + +; <label>:8 ; preds = %0 + call void @_ZdaPv(i8* %4) #5 + call void @_ZdaPv(i8* %5) #5 + br label %9 + +; <label>:9 ; preds = %0, %8 + ret void +} + +define void @_Z2p6bb(i1 zeroext %b1, i1 zeroext %b2) #0 { + %mStackData = alloca [10 x i32], align 16 + %1 = bitcast [10 x i32]* %mStackData to i8* + %2 = getelementptr inbounds [10 x i32]* %mStackData, i64 0, i64 0 + %3 = select i1 %b1, i32* %2, i32* @g5 + %4 = tail call noalias i8* @_Znam(i64 48) #4 + %5 = tail call noalias i8* @_Znam(i64 48) #4 + %.v = select i1 %b2, i8* %4, i8* %5 + %6 = bitcast i8* %.v to i32* + %7 = icmp eq i32* %6, %3 + br i1 %7, label %9, label %8 + +; CHECK-LABEL: @_Z2p6bb +; CHECK-NOT: icmp +; CHECK: ret void + +; <label>:8 ; preds = %0 + call void @_ZdaPv(i8* %4) #5 + call void @_ZdaPv(i8* %5) #5 + br label %9 + +; <label>:9 ; preds = %0, %8 + ret void +} + +; Here's another case involving multiple underlying objects, but this time we +; must keep the comparison (it might involve a regular pointer-typed function +; argument). + +define void @_Z4nopebbPi(i1 zeroext %b1, i1 zeroext %b2, i32* readnone %q) #0 { + %mStackData = alloca [10 x i32], align 16 + %1 = bitcast [10 x i32]* %mStackData to i8* + %2 = getelementptr inbounds [10 x i32]* %mStackData, i64 0, i64 0 + %3 = select i1 %b1, i32* %2, i32* %q + %4 = tail call noalias i8* @_Znam(i64 48) #4 + %5 = tail call noalias i8* @_Znam(i64 48) #4 + %.v = select i1 %b2, i8* %4, i8* %5 + %6 = bitcast i8* %.v to i32* + %7 = icmp eq i32* %6, %3 + br i1 %7, label %9, label %8 + +; CHECK-LABEL: @_Z4nopebbPi +; CHECK: icmp +; CHECK: ret void + +; <label>:8 ; preds = %0 + call void @_ZdaPv(i8* %4) #5 + call void @_ZdaPv(i8* %5) #5 + br label %9 + +; <label>:9 ; preds = %0, %8 + ret void +} + +define void @_Z2p3bb(i1 zeroext %b1, i1 zeroext %b2) #0 { + %mStackData = alloca [10 x i32], align 16 + %1 = bitcast [10 x i32]* %mStackData to i8* + %2 = getelementptr inbounds [10 x i32]* %mStackData, i64 0, i64 0 + %3 = select i1 %b1, i32* %2, i32* @g1 + %4 = tail call noalias i8* @_Znam(i64 48) #4 + %5 = tail call noalias i8* @_Znam(i64 48) #4 + %.v = select i1 %b2, i8* %4, i8* %5 + %6 = bitcast i8* %.v to i32* + %7 = icmp eq i32* %6, %3 + br i1 %7, label %9, label %8 + +; CHECK-LABEL: @_Z2p3bb +; CHECK: icmp +; CHECK: ret void + +; <label>:8 ; preds = %0 + call void @_ZdaPv(i8* %4) #5 + call void @_ZdaPv(i8* %5) #5 + br label %9 + +; <label>:9 ; preds = %0, %8 + ret void +} + +define void @_Z2p7bb(i1 zeroext %b1, i1 zeroext %b2) #0 { + %mStackData = alloca [10 x i32], align 16 + %1 = bitcast [10 x i32]* %mStackData to i8* + %2 = getelementptr inbounds [10 x i32]* %mStackData, i64 0, i64 0 + %3 = select i1 %b1, i32* %2, i32* @g6 + %4 = tail call noalias i8* @_Znam(i64 48) #4 + %5 = tail call noalias i8* @_Znam(i64 48) #4 + %.v = select i1 %b2, i8* %4, i8* %5 + %6 = bitcast i8* %.v to i32* + %7 = icmp eq i32* %6, %3 + br i1 %7, label %9, label %8 + +; CHECK-LABEL: @_Z2p7bb +; CHECK: icmp +; CHECK: ret void + +; <label>:8 ; preds = %0 + call void @_ZdaPv(i8* %4) #5 + call void @_ZdaPv(i8* %5) #5 + br label %9 + +; <label>:9 ; preds = %0, %8 + ret void +} + +define void @_Z2p2v(i32 %c) #0 { + %mStackData = alloca [10 x i32], i32 %c, align 16 + %1 = bitcast [10 x i32]* %mStackData to i8* + %2 = tail call noalias i8* @_Znam(i64 48) #4 + %3 = bitcast i8* %2 to i32* + %4 = getelementptr inbounds [10 x i32]* %mStackData, i64 0, i64 0 + %5 = icmp eq i32* %3, %4 + br i1 %5, label %7, label %6 + +; CHECK-LABEL: @_Z2p2v +; CHECK: icmp +; CHECK: ret void + +; <label>:6 ; preds = %0 + call void @_ZdaPv(i8* %2) #5 + br label %7 + +; <label>:7 ; preds = %0, %6 + ret void +} + +; Function Attrs: nobuiltin +declare noalias i8* @_Znam(i64) #2 + +; Function Attrs: nobuiltin nounwind +declare void @_ZdaPv(i8*) #3 + +attributes #0 = { uwtable } +attributes #1 = { nounwind } +attributes #2 = { nobuiltin } +attributes #3 = { nobuiltin nounwind } +attributes #4 = { builtin } +attributes #5 = { builtin nounwind } + diff --git a/test/Transforms/InstSimplify/rem.ll b/test/Transforms/InstSimplify/rem.ll index 80fa8e7b4831..f5ea45107e2a 100644 --- a/test/Transforms/InstSimplify/rem.ll +++ b/test/Transforms/InstSimplify/rem.ll @@ -15,3 +15,31 @@ define i32 @select2(i32 %x, i1 %b) { ret i32 %rem ; CHECK: ret i32 0 } + +define i32 @rem1(i32 %x, i32 %n) { +; CHECK-LABEL: @rem1( +; CHECK-NEXT: %mod = srem i32 %x, %n +; CHECK-NEXT: ret i32 %mod + %mod = srem i32 %x, %n + %mod1 = srem i32 %mod, %n + ret i32 %mod1 +} + +define i32 @rem2(i32 %x, i32 %n) { +; CHECK-LABEL: @rem2( +; CHECK-NEXT: %mod = urem i32 %x, %n +; CHECK-NEXT: ret i32 %mod + %mod = urem i32 %x, %n + %mod1 = urem i32 %mod, %n + ret i32 %mod1 +} + +define i32 @rem3(i32 %x, i32 %n) { +; CHECK-LABEL: @rem3( +; CHECK-NEXT: %[[srem:.*]] = srem i32 %x, %n +; CHECK-NEXT: %[[urem:.*]] = urem i32 %[[srem]], %n +; CHECK-NEXT: ret i32 %[[urem]] + %mod = srem i32 %x, %n + %mod1 = urem i32 %mod, %n + ret i32 %mod1 +} diff --git a/test/Transforms/InstSimplify/select.ll b/test/Transforms/InstSimplify/select.ll new file mode 100644 index 000000000000..1d45e5728e68 --- /dev/null +++ b/test/Transforms/InstSimplify/select.ll @@ -0,0 +1,161 @@ +; RUN: opt < %s -instsimplify -S | FileCheck %s + +define i32 @test1(i32 %x) { + %and = and i32 %x, 1 + %cmp = icmp eq i32 %and, 0 + %and1 = and i32 %x, -2 + %and1.x = select i1 %cmp, i32 %and1, i32 %x + ret i32 %and1.x +; CHECK-LABEL: @test1( +; CHECK: ret i32 %x +} + +define i32 @test2(i32 %x) { + %and = and i32 %x, 1 + %cmp = icmp ne i32 %and, 0 + %and1 = and i32 %x, -2 + %and1.x = select i1 %cmp, i32 %x, i32 %and1 + ret i32 %and1.x +; CHECK-LABEL: @test2( +; CHECK: ret i32 %x +} + +define i32 @test3(i32 %x) { + %and = and i32 %x, 1 + %cmp = icmp ne i32 %and, 0 + %and1 = and i32 %x, -2 + %and1.x = select i1 %cmp, i32 %and1, i32 %x + ret i32 %and1.x +; CHECK-LABEL: @test3( +; CHECK: %[[and:.*]] = and i32 %x, -2 +; CHECK: ret i32 %[[and]] +} + +define i32 @test4(i32 %X) { + %cmp = icmp slt i32 %X, 0 + %or = or i32 %X, -2147483648 + %cond = select i1 %cmp, i32 %X, i32 %or + ret i32 %cond +; CHECK-LABEL: @test4 +; CHECK: %[[or:.*]] = or i32 %X, -2147483648 +; CHECK: ret i32 %[[or]] +} + +define i32 @test5(i32 %X) { + %cmp = icmp slt i32 %X, 0 + %or = or i32 %X, -2147483648 + %cond = select i1 %cmp, i32 %or, i32 %X + ret i32 %cond +; CHECK-LABEL: @test5 +; CHECK: ret i32 %X +} + +define i32 @test6(i32 %X) { + %cmp = icmp slt i32 %X, 0 + %and = and i32 %X, 2147483647 + %cond = select i1 %cmp, i32 %and, i32 %X + ret i32 %cond +; CHECK-LABEL: @test6 +; CHECK: %[[and:.*]] = and i32 %X, 2147483647 +; CHECK: ret i32 %[[and]] +} + +define i32 @test7(i32 %X) { + %cmp = icmp slt i32 %X, 0 + %and = and i32 %X, 2147483647 + %cond = select i1 %cmp, i32 %X, i32 %and + ret i32 %cond +; CHECK-LABEL: @test7 +; CHECK: ret i32 %X +} + +define i32 @test8(i32 %X) { + %cmp = icmp sgt i32 %X, -1 + %or = or i32 %X, -2147483648 + %cond = select i1 %cmp, i32 %X, i32 %or + ret i32 %cond +; CHECK-LABEL: @test8 +; CHECK: ret i32 %X +} + +define i32 @test9(i32 %X) { + %cmp = icmp sgt i32 %X, -1 + %or = or i32 %X, -2147483648 + %cond = select i1 %cmp, i32 %or, i32 %X + ret i32 %cond +; CHECK-LABEL: @test9 +; CHECK: %[[or:.*]] = or i32 %X, -2147483648 +; CHECK: ret i32 %[[or]] +} + +define i32 @test10(i32 %X) { + %cmp = icmp sgt i32 %X, -1 + %and = and i32 %X, 2147483647 + %cond = select i1 %cmp, i32 %and, i32 %X + ret i32 %cond +; CHECK-LABEL: @test10 +; CHECK: ret i32 %X +} + +define i32 @test11(i32 %X) { + %cmp = icmp sgt i32 %X, -1 + %and = and i32 %X, 2147483647 + %cond = select i1 %cmp, i32 %X, i32 %and + ret i32 %cond +; CHECK-LABEL: @test11 +; CHECK: %[[and:.*]] = and i32 %X, 2147483647 +; CHECK: ret i32 %[[and]] +} + +; CHECK-LABEL: @select_icmp_and_8_eq_0_or_8( +; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 %x, 8 +; CHECK-NEXT: ret i32 [[OR]] +define i32 @select_icmp_and_8_eq_0_or_8(i32 %x) { + %and = and i32 %x, 8 + %cmp = icmp eq i32 %and, 0 + %or = or i32 %x, 8 + %or.x = select i1 %cmp, i32 %or, i32 %x + ret i32 %or.x +} + +; CHECK-LABEL: @select_icmp_and_8_ne_0_and_not_8( +; CHECK-NEXT: [[AND:%[a-z0-9]+]] = and i32 %x, -9 +; CHECK-NEXT: ret i32 [[AND]] +define i32 @select_icmp_and_8_ne_0_and_not_8(i32 %x) { + %and = and i32 %x, 8 + %cmp = icmp eq i32 %and, 0 + %and1 = and i32 %x, -9 + %x.and1 = select i1 %cmp, i32 %x, i32 %and1 + ret i32 %x.and1 +} + +; CHECK-LABEL: @select_icmp_and_8_eq_0_and_not_8( +; CHECK-NEXT: ret i32 %x +define i32 @select_icmp_and_8_eq_0_and_not_8(i32 %x) { + %and = and i32 %x, 8 + %cmp = icmp eq i32 %and, 0 + %and1 = and i32 %x, -9 + %and1.x = select i1 %cmp, i32 %and1, i32 %x + ret i32 %and1.x +} + +; CHECK-LABEL: @select_icmp_x_and_8_eq_0_y_and_not_8( +; CHECK: select i1 %cmp, i64 %y, i64 %and1 +define i64 @select_icmp_x_and_8_eq_0_y_and_not_8(i32 %x, i64 %y) { + %and = and i32 %x, 8 + %cmp = icmp eq i32 %and, 0 + %and1 = and i64 %y, -9 + %y.and1 = select i1 %cmp, i64 %y, i64 %and1 + ret i64 %y.and1 +} + +; CHECK-LABEL: @select_icmp_x_and_8_ne_0_y_and_not_8( +; CHECK: select i1 %cmp, i64 %and1, i64 %y +define i64 @select_icmp_x_and_8_ne_0_y_and_not_8(i32 %x, i64 %y) { + %and = and i32 %x, 8 + %cmp = icmp eq i32 %and, 0 + %and1 = and i64 %y, -9 + %and1.y = select i1 %cmp, i64 %and1, i64 %y + ret i64 %and1.y +} + diff --git a/test/Transforms/InstSimplify/shr-nop.ll b/test/Transforms/InstSimplify/shr-nop.ll new file mode 100644 index 000000000000..b0dc8731a112 --- /dev/null +++ b/test/Transforms/InstSimplify/shr-nop.ll @@ -0,0 +1,346 @@ +; RUN: opt < %s -instsimplify -S | FileCheck %s + +; CHECK-LABEL: @foo +; CHECK: %[[and:.*]] = and i32 %x, 1 +; CHECK-NEXT: %[[add:.*]] = add i32 %[[and]], -1 +; CHECK-NEXT: ret i32 %[[add]] +define i32 @foo(i32 %x) { + %o = and i32 %x, 1 + %n = add i32 %o, -1 + %t = ashr i32 %n, 17 + ret i32 %t +} + +; CHECK-LABEL: @exact_lshr_eq_both_zero +; CHECK-NEXT: ret i1 true +define i1 @exact_lshr_eq_both_zero(i8 %a) { + %shr = lshr exact i8 0, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_eq_both_zero +; CHECK-NEXT: ret i1 true +define i1 @exact_ashr_eq_both_zero(i8 %a) { + %shr = ashr exact i8 0, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_eq_both_zero +; CHECK-NEXT: ret i1 true +define i1 @nonexact_ashr_eq_both_zero(i8 %a) { + %shr = ashr i8 0, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_ne_both_zero +; CHECK-NEXT: ret i1 false +define i1 @exact_lshr_ne_both_zero(i8 %a) { + %shr = lshr exact i8 0, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_ne_both_zero +; CHECK-NEXT: ret i1 false +define i1 @exact_ashr_ne_both_zero(i8 %a) { + %shr = ashr exact i8 0, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_ne_both_zero +; CHECK-NEXT: ret i1 false +define i1 @nonexact_lshr_ne_both_zero(i8 %a) { + %shr = lshr i8 0, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_ne_both_zero +; CHECK-NEXT: ret i1 false +define i1 @nonexact_ashr_ne_both_zero(i8 %a) { + %shr = ashr i8 0, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_eq_last_zero +; CHECK-NEXT: ret i1 false +define i1 @exact_lshr_eq_last_zero(i8 %a) { + %shr = lshr exact i8 128, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_eq_last_zero +; CHECK-NEXT: ret i1 false +define i1 @exact_ashr_eq_last_zero(i8 %a) { + %shr = ashr exact i8 -128, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_eq_both_zero +; CHECK-NEXT: ret i1 true +define i1 @nonexact_lshr_eq_both_zero(i8 %a) { + %shr = lshr i8 0, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_ne_last_zero +; CHECK-NEXT: ret i1 true +define i1 @exact_lshr_ne_last_zero(i8 %a) { + %shr = lshr exact i8 128, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_ne_last_zero +; CHECK-NEXT: ret i1 true +define i1 @exact_ashr_ne_last_zero(i8 %a) { + %shr = ashr exact i8 -128, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_eq_last_zero +; CHECK-NEXT: ret i1 false +define i1 @nonexact_lshr_eq_last_zero(i8 %a) { + %shr = lshr i8 128, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_eq_last_zero +; CHECK-NEXT: ret i1 false +define i1 @nonexact_ashr_eq_last_zero(i8 %a) { + %shr = ashr i8 -128, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_ne_last_zero +; CHECK-NEXT: ret i1 true +define i1 @nonexact_lshr_ne_last_zero(i8 %a) { + %shr = lshr i8 128, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_ne_last_zero +; CHECK-NEXT: ret i1 true +define i1 @nonexact_ashr_ne_last_zero(i8 %a) { + %shr = ashr i8 -128, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @lshr_eq_first_zero +; CHECK-NEXT: ret i1 false +define i1 @lshr_eq_first_zero(i8 %a) { + %shr = lshr i8 0, %a + %cmp = icmp eq i8 %shr, 2 + ret i1 %cmp +} + +; CHECK-LABEL: @ashr_eq_first_zero +; CHECK-NEXT: ret i1 false +define i1 @ashr_eq_first_zero(i8 %a) { + %shr = ashr i8 0, %a + %cmp = icmp eq i8 %shr, 2 + ret i1 %cmp +} + +; CHECK-LABEL: @lshr_ne_first_zero +; CHECK-NEXT: ret i1 true +define i1 @lshr_ne_first_zero(i8 %a) { + %shr = lshr i8 0, %a + %cmp = icmp ne i8 %shr, 2 + ret i1 %cmp +} + +; CHECK-LABEL: @ashr_ne_first_zero +; CHECK-NEXT: ret i1 true +define i1 @ashr_ne_first_zero(i8 %a) { + %shr = ashr i8 0, %a + %cmp = icmp ne i8 %shr, 2 + ret i1 %cmp +} + +; CHECK-LABEL: @ashr_eq_both_minus1 +; CHECK-NEXT: ret i1 true +define i1 @ashr_eq_both_minus1(i8 %a) { + %shr = ashr i8 -1, %a + %cmp = icmp eq i8 %shr, -1 + ret i1 %cmp +} + +; CHECK-LABEL: @ashr_ne_both_minus1 +; CHECK-NEXT: ret i1 false +define i1 @ashr_ne_both_minus1(i8 %a) { + %shr = ashr i8 -1, %a + %cmp = icmp ne i8 %shr, -1 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_eq_both_minus1 +; CHECK-NEXT: ret i1 true +define i1 @exact_ashr_eq_both_minus1(i8 %a) { + %shr = ashr exact i8 -1, %a + %cmp = icmp eq i8 %shr, -1 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_ne_both_minus1 +; CHECK-NEXT: ret i1 false +define i1 @exact_ashr_ne_both_minus1(i8 %a) { + %shr = ashr exact i8 -1, %a + %cmp = icmp ne i8 %shr, -1 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_eq_opposite_msb +; CHECK-NEXT: ret i1 false +define i1 @exact_ashr_eq_opposite_msb(i8 %a) { + %shr = ashr exact i8 -128, %a + %cmp = icmp eq i8 %shr, 1 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_eq_noexactlog +; CHECK-NEXT: ret i1 false +define i1 @exact_ashr_eq_noexactlog(i8 %a) { + %shr = ashr exact i8 -90, %a + %cmp = icmp eq i8 %shr, -30 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_ne_opposite_msb +; CHECK-NEXT: ret i1 true +define i1 @exact_ashr_ne_opposite_msb(i8 %a) { + %shr = ashr exact i8 -128, %a + %cmp = icmp ne i8 %shr, 1 + ret i1 %cmp +} + +; CHECK-LABEL: @ashr_eq_opposite_msb +; CHECK-NEXT: ret i1 false +define i1 @ashr_eq_opposite_msb(i8 %a) { + %shr = ashr i8 -128, %a + %cmp = icmp eq i8 %shr, 1 + ret i1 %cmp +} + +; CHECK-LABEL: @ashr_ne_opposite_msb +; CHECK-NEXT: ret i1 true +define i1 @ashr_ne_opposite_msb(i8 %a) { + %shr = ashr i8 -128, %a + %cmp = icmp ne i8 %shr, 1 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_eq_shift_gt +; CHECK-NEXT : ret i1 false +define i1 @exact_ashr_eq_shift_gt(i8 %a) { + %shr = ashr exact i8 -2, %a + %cmp = icmp eq i8 %shr, -8 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_ne_shift_gt +; CHECK-NEXT : ret i1 true +define i1 @exact_ashr_ne_shift_gt(i8 %a) { + %shr = ashr exact i8 -2, %a + %cmp = icmp ne i8 %shr, -8 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_eq_shift_gt +; CHECK-NEXT : ret i1 false +define i1 @nonexact_ashr_eq_shift_gt(i8 %a) { + %shr = ashr i8 -2, %a + %cmp = icmp eq i8 %shr, -8 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_ashr_ne_shift_gt +; CHECK-NEXT : ret i1 true +define i1 @nonexact_ashr_ne_shift_gt(i8 %a) { + %shr = ashr i8 -2, %a + %cmp = icmp ne i8 %shr, -8 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_eq_shift_gt +; CHECK-NEXT: ret i1 false +define i1 @exact_lshr_eq_shift_gt(i8 %a) { + %shr = lshr exact i8 2, %a + %cmp = icmp eq i8 %shr, 8 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_ne_shift_gt +; CHECK-NEXT: ret i1 true +define i1 @exact_lshr_ne_shift_gt(i8 %a) { + %shr = lshr exact i8 2, %a + %cmp = icmp ne i8 %shr, 8 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_eq_shift_gt +; CHECK-NEXT : ret i1 false +define i1 @nonexact_lshr_eq_shift_gt(i8 %a) { + %shr = lshr i8 2, %a + %cmp = icmp eq i8 %shr, 8 + ret i1 %cmp +} + +; CHECK-LABEL: @nonexact_lshr_ne_shift_gt +; CHECK-NEXT : ret i1 true +define i1 @nonexact_lshr_ne_shift_gt(i8 %a) { + %shr = ashr i8 2, %a + %cmp = icmp ne i8 %shr, 8 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_ashr_ne_noexactlog +; CHECK-NEXT: ret i1 true +define i1 @exact_ashr_ne_noexactlog(i8 %a) { + %shr = ashr exact i8 -90, %a + %cmp = icmp ne i8 %shr, -30 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_eq_noexactlog +; CHECK-NEXT: ret i1 false +define i1 @exact_lshr_eq_noexactlog(i8 %a) { + %shr = lshr exact i8 90, %a + %cmp = icmp eq i8 %shr, 30 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_ne_noexactlog +; CHECK-NEXT: ret i1 true +define i1 @exact_lshr_ne_noexactlog(i8 %a) { + %shr = lshr exact i8 90, %a + %cmp = icmp ne i8 %shr, 30 + ret i1 %cmp +} + +; CHECK-LABEL: @exact_lshr_lowbit +; CHECK-NEXT: ret i32 7 +define i32 @exact_lshr_lowbit(i32 %shiftval) { + %shr = lshr exact i32 7, %shiftval + ret i32 %shr +} + +; CHECK-LABEL: @exact_ashr_lowbit +; CHECK-NEXT: ret i32 7 +define i32 @exact_ashr_lowbit(i32 %shiftval) { + %shr = ashr exact i32 7, %shiftval + ret i32 %shr +} diff --git a/test/Transforms/InstSimplify/undef.ll b/test/Transforms/InstSimplify/undef.ll index 181c2efa2dc0..e8b49b6397db 100644 --- a/test/Transforms/InstSimplify/undef.ll +++ b/test/Transforms/InstSimplify/undef.ll @@ -160,3 +160,108 @@ define <4 x i8> @test19(<4 x i8> %a) { %b = shl <4 x i8> %a, <i8 8, i8 9, i8 undef, i8 -1> ret <4 x i8> %b } + +; CHECK-LABEL: @test20 +; CHECK: ret i32 undef +define i32 @test20(i32 %a) { + %b = udiv i32 %a, 0 + ret i32 %b +} + +; CHECK-LABEL: @test21 +; CHECK: ret i32 undef +define i32 @test21(i32 %a) { + %b = sdiv i32 %a, 0 + ret i32 %b +} + +; CHECK-LABEL: @test22 +; CHECK: ret i32 undef +define i32 @test22(i32 %a) { + %b = ashr exact i32 undef, %a + ret i32 %b +} + +; CHECK-LABEL: @test23 +; CHECK: ret i32 undef +define i32 @test23(i32 %a) { + %b = lshr exact i32 undef, %a + ret i32 %b +} + +; CHECK-LABEL: @test24 +; CHECK: ret i32 undef +define i32 @test24() { + %b = udiv i32 undef, 0 + ret i32 %b +} + +; CHECK-LABEL: @test25 +; CHECK: ret i32 undef +define i32 @test25() { + %b = lshr i32 0, undef + ret i32 %b +} + +; CHECK-LABEL: @test26 +; CHECK: ret i32 undef +define i32 @test26() { + %b = ashr i32 0, undef + ret i32 %b +} + +; CHECK-LABEL: @test27 +; CHECK: ret i32 undef +define i32 @test27() { + %b = shl i32 0, undef + ret i32 %b +} + +; CHECK-LABEL: @test28 +; CHECK: ret i32 undef +define i32 @test28(i32 %a) { + %b = shl nsw i32 undef, %a + ret i32 %b +} + +; CHECK-LABEL: @test29 +; CHECK: ret i32 undef +define i32 @test29(i32 %a) { + %b = shl nuw i32 undef, %a + ret i32 %b +} + +; CHECK-LABEL: @test30 +; CHECK: ret i32 undef +define i32 @test30(i32 %a) { + %b = shl nsw nuw i32 undef, %a + ret i32 %b +} + +; CHECK-LABEL: @test31 +; CHECK: ret i32 0 +define i32 @test31(i32 %a) { + %b = shl i32 undef, %a + ret i32 %b +} + +; CHECK-LABEL: @test32 +; CHECK: ret i32 undef +define i32 @test32(i32 %a) { + %b = shl i32 undef, 0 + ret i32 %b +} + +; CHECK-LABEL: @test33 +; CHECK: ret i32 undef +define i32 @test33(i32 %a) { + %b = ashr i32 undef, 0 + ret i32 %b +} + +; CHECK-LABEL: @test34 +; CHECK: ret i32 undef +define i32 @test34(i32 %a) { + %b = lshr i32 undef, 0 + ret i32 %b +} diff --git a/test/Transforms/InstSimplify/vector_ptr_bitcast.ll b/test/Transforms/InstSimplify/vector_ptr_bitcast.ll new file mode 100644 index 000000000000..607892ae74d2 --- /dev/null +++ b/test/Transforms/InstSimplify/vector_ptr_bitcast.ll @@ -0,0 +1,35 @@ +; RUN: opt -S -instsimplify < %s | FileCheck %s +target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" + +%mst = type { i8*, i8* } +%mst2 = type { i32*, i32*, i32*, i32* } + +@a = private unnamed_addr constant %mst { i8* inttoptr (i64 -1 to i8*), + i8* inttoptr (i64 -1 to i8*)}, + align 8 +@b = private unnamed_addr constant %mst2 { i32* inttoptr (i64 42 to i32*), + i32* inttoptr (i64 67 to i32*), + i32* inttoptr (i64 33 to i32*), + i32* inttoptr (i64 58 to i32*)}, + align 8 + +define i64 @fn() { + %x = load <2 x i8*>* bitcast (%mst* @a to <2 x i8*>*), align 8 + %b = extractelement <2 x i8*> %x, i32 0 + %c = ptrtoint i8* %b to i64 + ; CHECK-LABEL: @fn + ; CHECK-NEXT: ret i64 -1 + ret i64 %c +} + +define i64 @fn2() { + %x = load <4 x i32*>* bitcast (%mst2* @b to <4 x i32*>*), align 8 + %b = extractelement <4 x i32*> %x, i32 0 + %c = extractelement <4 x i32*> %x, i32 3 + %d = ptrtoint i32* %b to i64 + %e = ptrtoint i32* %c to i64 + %r = add i64 %d, %e + ; CHECK-LABEL: @fn2 + ; CHECK-NEXT: ret i64 100 + ret i64 %r +} diff --git a/test/Transforms/Internalize/2009-01-05-InternalizeAliases.ll b/test/Transforms/Internalize/2009-01-05-InternalizeAliases.ll index 16bfe2a46091..16523886a068 100644 --- a/test/Transforms/Internalize/2009-01-05-InternalizeAliases.ll +++ b/test/Transforms/Internalize/2009-01-05-InternalizeAliases.ll @@ -4,10 +4,10 @@ ; CHECK: @A = internal global i32 0 @B = alias i32* @A -; CHECK: @B = alias internal i32* @A +; CHECK: @B = internal alias i32* @A @C = alias i32* @A -; CHECK: @C = alias internal i32* @A +; CHECK: @C = internal alias i32* @A define i32 @main() { %tmp = load i32* @C diff --git a/test/Transforms/Internalize/local-visibility.ll b/test/Transforms/Internalize/local-visibility.ll index c24d4b7f32a0..b09a136e5263 100644 --- a/test/Transforms/Internalize/local-visibility.ll +++ b/test/Transforms/Internalize/local-visibility.ll @@ -10,9 +10,9 @@ ; CHECK: @protected.variable = internal global i32 0 @protected.variable = protected global i32 0 -; CHECK: @hidden.alias = alias internal i32* @global +; CHECK: @hidden.alias = internal alias i32* @global @hidden.alias = hidden alias i32* @global -; CHECK: @protected.alias = alias internal i32* @global +; CHECK: @protected.alias = internal alias i32* @global @protected.alias = protected alias i32* @global ; CHECK: define internal void @hidden.function() { diff --git a/test/Transforms/JumpThreading/assume-edge-dom.ll b/test/Transforms/JumpThreading/assume-edge-dom.ll new file mode 100644 index 000000000000..f1d0f41e2505 --- /dev/null +++ b/test/Transforms/JumpThreading/assume-edge-dom.ll @@ -0,0 +1,39 @@ +; RUN: opt -S -jump-threading < %s | FileCheck %s + +declare i8* @escape() +declare void @llvm.assume(i1) + +define i1 @test1(i1 %cond) { +entry: + br i1 %cond, label %taken, label %not_taken + +; CHECK-LABEL: @test1 +; CHECK: br i1 %cond, label %no, label %yes +; CHECK: ret i1 true + +taken: + %res1 = call i8* @escape() + %a = icmp eq i8* %res1, null + tail call void @llvm.assume(i1 %a) + br label %done +not_taken: + %res2 = call i8* @escape() + %b = icmp ne i8* %res2, null + tail call void @llvm.assume(i1 %b) + br label %done + +; An assume that can be used to simplify this comparison dominates each +; predecessor branch (although no assume dominates the cmp itself). Make sure +; this still can be simplified. + +done: + %res = phi i8* [ %res1, %taken ], [ %res2, %not_taken ] + %cnd = icmp ne i8* %res, null + br i1 %cnd, label %yes, label %no + +yes: + ret i1 true +no: + ret i1 false +} + diff --git a/test/Transforms/JumpThreading/assume.ll b/test/Transforms/JumpThreading/assume.ll new file mode 100644 index 000000000000..89dd0a954c01 --- /dev/null +++ b/test/Transforms/JumpThreading/assume.ll @@ -0,0 +1,68 @@ +; RUN: opt -S -jump-threading -dce < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: nounwind uwtable +define i32 @test1(i32 %a, i32 %b) #0 { +entry: + %cmp = icmp sgt i32 %a, 5 + tail call void @llvm.assume(i1 %cmp) + %cmp1 = icmp sgt i32 %b, 1234 + br i1 %cmp1, label %if.then, label %if.else + +; CHECK-LABEL: @test1 +; CHECK: icmp sgt i32 %a, 5 +; CHECK: call void @llvm.assume +; CHECK-NOT: icmp sgt i32 %a, 3 +; CHECK: ret i32 + +if.then: ; preds = %entry + %cmp2 = icmp sgt i32 %a, 3 + br i1 %cmp2, label %if.then3, label %return + +if.then3: ; preds = %if.then + tail call void (...)* @bar() #1 + br label %return + +if.else: ; preds = %entry + tail call void (...)* @car() #1 + br label %return + +return: ; preds = %if.else, %if.then, %if.then3 + %retval.0 = phi i32 [ 1, %if.then3 ], [ 0, %if.then ], [ 0, %if.else ] + ret i32 %retval.0 +} + +define i32 @test2(i32 %a) #0 { +entry: + %cmp = icmp sgt i32 %a, 5 + tail call void @llvm.assume(i1 %cmp) + %cmp1 = icmp sgt i32 %a, 3 + br i1 %cmp1, label %if.then, label %return + +; CHECK-LABEL: @test2 +; CHECK: icmp sgt i32 %a, 5 +; CHECK: tail call void @llvm.assume +; CHECK: tail call void (...)* @bar() +; CHECK: ret i32 1 + + +if.then: ; preds = %entry + tail call void (...)* @bar() #1 + br label %return + +return: ; preds = %entry, %if.then + %retval.0 = phi i32 [ 1, %if.then ], [ 0, %entry ] + ret i32 %retval.0 +} + +; Function Attrs: nounwind +declare void @llvm.assume(i1) #1 + +declare void @bar(...) + +declare void @car(...) + +attributes #0 = { nounwind uwtable } +attributes #1 = { nounwind } + diff --git a/test/Transforms/JumpThreading/conservative-lvi.ll b/test/Transforms/JumpThreading/conservative-lvi.ll new file mode 100644 index 000000000000..1ea8cdc4693a --- /dev/null +++ b/test/Transforms/JumpThreading/conservative-lvi.ll @@ -0,0 +1,58 @@ +; RUN: opt -jump-threading -S %s | FileCheck %s + +; Check that we thread arg2neg -> checkpos -> end. +; +; LazyValueInfo would previously fail to analyze the value of %arg in arg2neg +; because its predecessing blocks (checkneg) hadn't been processed yet (PR21238) + +; CHECK-LABEL: @test_jump_threading +; CHECK: arg2neg: +; CHECK-NEXT: br i1 %arg1, label %end, label %checkpos.thread +; CHECK: checkpos.thread: +; CHECK-NEXT: br label %end + +define i32 @test_jump_threading(i1 %arg1, i32 %arg2) { +checkneg: + %cmp = icmp slt i32 %arg2, 0 + br i1 %cmp, label %arg2neg, label %checkpos + +arg2neg: + br i1 %arg1, label %end, label %checkpos + +checkpos: + %cmp2 = icmp sgt i32 %arg2, 0 + br i1 %cmp2, label %arg2pos, label %end + +arg2pos: + br label %end + +end: + %0 = phi i32 [ 1, %arg2neg ], [ 2, %checkpos ], [ 3, %arg2pos ] + ret i32 %0 +} + + +; arg2neg has an edge back to itself. If LazyValueInfo is not careful when +; visiting predecessors, it could get into an infinite loop. + +; CHECK-LABEL: test_infinite_loop + +define i32 @test_infinite_loop(i1 %arg1, i32 %arg2) { +checkneg: + %cmp = icmp slt i32 %arg2, 0 + br i1 %cmp, label %arg2neg, label %checkpos + +arg2neg: + br i1 %arg1, label %arg2neg, label %checkpos + +checkpos: + %cmp2 = icmp sgt i32 %arg2, 0 + br i1 %cmp2, label %arg2pos, label %end + +arg2pos: + br label %end + +end: + %0 = phi i32 [ 2, %checkpos ], [ 3, %arg2pos ] + ret i32 %0 +} diff --git a/test/Transforms/JumpThreading/pr22086.ll b/test/Transforms/JumpThreading/pr22086.ll new file mode 100644 index 000000000000..35d9aa5b1841 --- /dev/null +++ b/test/Transforms/JumpThreading/pr22086.ll @@ -0,0 +1,28 @@ +; RUN: opt -S -jump-threading < %s | FileCheck %s + + +; CHECK-LABEL: @f( +; CHECK-LABEL: entry: +; CHECK-NEXT: br label %[[loop:.*]] +; CHECK: [[loop]]: +; CHECK-NEXT: br label %[[loop]] + +define void @f() { +entry: + br label %for.cond1 + +if.end16: + %phi1 = phi i32 [ undef, %for.cond1 ] + %g.3 = phi i32 [ %g.1, %for.cond1 ] + %sext = shl i32 %g.3, 16 + %conv20 = ashr exact i32 %sext, 16 + %tobool21 = icmp eq i32 %phi1, 0 + br i1 %tobool21, label %lor.rhs, label %for.cond1 + +for.cond1: + %g.1 = phi i32 [ 0, %entry ], [ 0, %lor.rhs ], [ %g.3, %if.end16 ] + br i1 undef, label %lor.rhs, label %if.end16 + +lor.rhs: + br label %for.cond1 +} diff --git a/test/Transforms/JumpThreading/thread-loads.ll b/test/Transforms/JumpThreading/thread-loads.ll index e5bf64b9e256..4351f9918109 100644 --- a/test/Transforms/JumpThreading/thread-loads.ll +++ b/test/Transforms/JumpThreading/thread-loads.ll @@ -75,7 +75,38 @@ bb3: ; preds = %bb1 ret i32 %res.0 } -!0 = metadata !{metadata !3, metadata !3, i64 0} -!1 = metadata !{metadata !"omnipotent char", metadata !2} -!2 = metadata !{metadata !"Simple C/C++ TBAA", null} -!3 = metadata !{metadata !"int", metadata !1} +define i32 @test3(i8** %x, i1 %f) { +; Correctly thread loads of different (but compatible) types, placing bitcasts +; as necessary in the predecessors. This is especially tricky because the same +; predecessor ends up with two entries in the PHI node and they must share +; a single cast. +; CHECK-LABEL: @test3( +entry: + %0 = bitcast i8** %x to i32** + %1 = load i32** %0, align 8 + br i1 %f, label %if.end57, label %if.then56 +; CHECK: %[[LOAD:.*]] = load i32** +; CHECK: %[[CAST:.*]] = bitcast i32* %[[LOAD]] to i8* + +if.then56: + br label %if.end57 + +if.end57: + %2 = load i8** %x, align 8 + %tobool59 = icmp eq i8* %2, null + br i1 %tobool59, label %return, label %if.then60 +; CHECK: %[[PHI:.*]] = phi i8* [ %[[CAST]], %[[PRED:[^ ]+]] ], [ %[[CAST]], %[[PRED]] ] +; CHECK-NEXT: %[[CMP:.*]] = icmp eq i8* %[[PHI]], null +; CHECK-NEXT: br i1 %[[CMP]] + +if.then60: + ret i32 42 + +return: + ret i32 13 +} + +!0 = !{!3, !3, i64 0} +!1 = !{!"omnipotent char", !2} +!2 = !{!"Simple C/C++ TBAA", null} +!3 = !{!"int", !1} diff --git a/test/Transforms/LCSSA/indirectbr.ll b/test/Transforms/LCSSA/indirectbr.ll index 96564486e820..345395bee01b 100644 --- a/test/Transforms/LCSSA/indirectbr.ll +++ b/test/Transforms/LCSSA/indirectbr.ll @@ -1,11 +1,11 @@ -; RUN: opt < %s -lcssa -verify-loop-info -verify-dom-info -disable-output -; PR5437 +; RUN: opt < %s -loop-simplify -lcssa -verify-loop-info -verify-dom-info -S | FileCheck %s ; LCSSA should work correctly in the case of an indirectbr that exits ; the loop, and the loop has exits with predecessors not within the loop ; (and btw these edges are unsplittable due to the indirectbr). - -define i32 @js_Interpret() nounwind { +; PR5437 +define i32 @test0() nounwind { +; CHECK-LABEL: @test0 entry: br i1 undef, label %"4", label %"3" @@ -540,3 +540,35 @@ entry: "1862": ; preds = %"1836", %"692" unreachable } + +; An exit for Loop L1 may be the header of a disjoint Loop L2. Thus, when we +; create PHIs in one of such exits we are also inserting PHIs in L2 header. This +; could break LCSSA form for L2 because these inserted PHIs can also have uses +; in L2 exits. Test that we don't assert/crash on that. +define void @test1() { +; CHECK-LABEL: @test1 + br label %lab1 + +lab1: + %tmp21 = add i32 undef, 677038203 + br i1 undef, label %lab2, label %exit + +lab2: + indirectbr i8* undef, [label %lab1, label %lab3] + +lab3: +; CHECK: %tmp21.lcssa1 = phi i32 [ %tmp21.lcssa1, %lab4 ], [ %tmp21, %lab2 ] + %tmp12 = phi i32 [ %tmp21, %lab2 ], [ %tmp12, %lab4 ] + br i1 undef, label %lab5, label %lab4 + +lab4: + br label %lab3 + +lab5: +; CHECK: %tmp21.lcssa1.lcssa = phi i32 [ %tmp21.lcssa1, %lab3 ] + %tmp15 = add i32 %tmp12, undef + br label %exit + +exit: + ret void +} diff --git a/test/Transforms/LICM/2011-04-06-PromoteResultOfPromotion.ll b/test/Transforms/LICM/2011-04-06-PromoteResultOfPromotion.ll index 7cf7a323552d..5587142dcf76 100644 --- a/test/Transforms/LICM/2011-04-06-PromoteResultOfPromotion.ll +++ b/test/Transforms/LICM/2011-04-06-PromoteResultOfPromotion.ll @@ -30,10 +30,10 @@ for.end: ; preds = %for.inc ret void } -!0 = metadata !{metadata !5, metadata !5, i64 0} -!1 = metadata !{metadata !"omnipotent char", metadata !2} -!2 = metadata !{metadata !"Simple C/C++ TBAA", null} -!3 = metadata !{metadata !"short", metadata !1} -!4 = metadata !{metadata !6, metadata !6, i64 0} -!5 = metadata !{metadata !"any pointer", metadata !1} -!6 = metadata !{metadata !"int", metadata !1} +!0 = !{!5, !5, i64 0} +!1 = !{!"omnipotent char", !2} +!2 = !{!"Simple C/C++ TBAA", null} +!3 = !{!"short", !1} +!4 = !{!6, !6, i64 0} +!5 = !{!"any pointer", !1} +!6 = !{!"int", !1} diff --git a/test/Transforms/LICM/2014-09-10-doFinalizationAssert.ll b/test/Transforms/LICM/2014-09-10-doFinalizationAssert.ll new file mode 100644 index 000000000000..17ae716dd478 --- /dev/null +++ b/test/Transforms/LICM/2014-09-10-doFinalizationAssert.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -scalar-evolution -licm -loop-unroll -disable-output +; Test triggered an assertion in doFinalization() because loop unroll was deleting +; the inner loop which caused the loop to not get removed from the +; LoopToAliasSetMap. +; Test case taken from test/Transforms/LoopUnroll/unloop.ll. + +declare i1 @check() nounwind +define void @skiplevelexit() nounwind { +entry: + br label %outer + +outer: + br label %inner + +inner: + %iv = phi i32 [ 0, %outer ], [ %inc, %tail ] + %inc = add i32 %iv, 1 + call zeroext i1 @check() + br i1 true, label %outer.backedge, label %tail + +tail: + br i1 false, label %inner, label %exit + +outer.backedge: + br label %outer + +exit: + ret void +} + diff --git a/test/Transforms/LICM/PR19798.ll b/test/Transforms/LICM/PR19798.ll new file mode 100644 index 000000000000..82befb09666c --- /dev/null +++ b/test/Transforms/LICM/PR19798.ll @@ -0,0 +1,22 @@ +; RUN: opt -licm -S < %s | FileCheck %s + +define void @f() { +; CHECK-LABEL: @f( +entry: + br label %bb0 + +bb0: + %tobool7 = icmp eq i1 undef, undef + br label %bb1 + +bb1: + br i1 undef, label %bb0, label %bb0 + +unreachable: +; CHECK-LABEL: unreachable: +; CHECK: br i1 undef, label %unreachable, label %unreachable + br i1 %tobool7, label %unreachable, label %unreachable + +bb3: + unreachable +} diff --git a/test/Transforms/LICM/debug-value.ll b/test/Transforms/LICM/debug-value.ll index e5c774ff8e9d..b49c559672a6 100644 --- a/test/Transforms/LICM/debug-value.ll +++ b/test/Transforms/LICM/debug-value.ll @@ -15,7 +15,7 @@ if.then: ; preds = %for.body if.then27: ; preds = %if.then ; CHECK: tail call void @llvm.dbg.value - tail call void @llvm.dbg.value(metadata !18, i64 0, metadata !19), !dbg !21 + tail call void @llvm.dbg.value(metadata double undef, i64 0, metadata !19, metadata !{}), !dbg !21 br label %for.body61.us if.end.if.end.split_crit_edge.critedge: ; preds = %if.then @@ -31,35 +31,35 @@ for.end104: ; preds = %for.cond.backedge ret void, !dbg !24 } -declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone !llvm.module.flags = !{!26} !llvm.dbg.sp = !{!0, !6, !9, !10} -!0 = metadata !{i32 589870, metadata !25, metadata !1, metadata !"idamax", metadata !"idamax", metadata !"", i32 112, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 false, null, null, null, null, i32 0} ; [ DW_TAG_subprogram ] -!1 = metadata !{i32 589865, metadata !25} ; [ DW_TAG_file_type ] -!2 = metadata !{i32 589841, metadata !25, i32 12, metadata !"clang version 2.9 (trunk 127169)", i1 true, metadata !"", i32 0, metadata !8, metadata !8, metadata !8, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!3 = metadata !{i32 589845, metadata !25, metadata !1, metadata !"", i32 0, i64 0, i64 0, i32 0, i32 0, null, metadata !4, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] -!4 = metadata !{metadata !5} -!5 = metadata !{i32 589860, null, metadata !2, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!6 = metadata !{i32 589870, metadata !25, metadata !1, metadata !"dscal", metadata !"dscal", metadata !"", i32 206, metadata !7, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 false, null, null, null, null, i32 0} ; [ DW_TAG_subprogram ] -!7 = metadata !{i32 589845, metadata !25, metadata !1, metadata !"", i32 0, i64 0, i64 0, i32 0, i32 0, null, metadata !8, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!8 = metadata !{null} -!9 = metadata !{i32 589870, metadata !25, metadata !1, metadata !"daxpy", metadata !"daxpy", metadata !"", i32 230, metadata !7, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 false, null, null, null, null, i32 0} ; [ DW_TAG_subprogram ] -!10 = metadata !{i32 589870, metadata !25, metadata !1, metadata !"dgefa", metadata !"dgefa", metadata !"", i32 267, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, null, null, null, null, i32 0} ; [ DW_TAG_subprogram ] [line 267] [def] [scope 0] [dgefa] -!11 = metadata !{i32 281, i32 9, metadata !12, null} -!12 = metadata !{i32 589835, metadata !25, metadata !13, i32 272, i32 5, i32 32} ; [ DW_TAG_lexical_block ] -!13 = metadata !{i32 589835, metadata !25, metadata !14, i32 271, i32 5, i32 31} ; [ DW_TAG_lexical_block ] -!14 = metadata !{i32 589835, metadata !25, metadata !10, i32 267, i32 1, i32 30} ; [ DW_TAG_lexical_block ] -!15 = metadata !{i32 271, i32 5, metadata !14, null} -!16 = metadata !{i32 284, i32 10, metadata !17, null} -!17 = metadata !{i32 589835, metadata !25, metadata !12, i32 282, i32 9, i32 33} ; [ DW_TAG_lexical_block ] -!18 = metadata !{double undef} -!19 = metadata !{i32 590080, metadata !14, metadata !"temp", metadata !1, i32 268, metadata !20, i32 0} ; [ DW_TAG_auto_variable ] -!20 = metadata !{i32 589860, null, metadata !2, metadata !"double", i32 0, i64 64, i64 64, i64 0, i32 0, i32 4} ; [ DW_TAG_base_type ] -!21 = metadata !{i32 286, i32 14, metadata !22, null} -!22 = metadata !{i32 589835, metadata !25, metadata !17, i32 285, i32 13, i32 34} ; [ DW_TAG_lexical_block ] -!23 = metadata !{i32 296, i32 13, metadata !17, null} -!24 = metadata !{i32 313, i32 1, metadata !14, null} -!25 = metadata !{metadata !"/Volumes/Lalgate/work/llvm/projects/llvm-test/SingleSource/Benchmarks/CoyoteBench/lpbench.c", metadata !"/private/tmp"} -!26 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x2e\00idamax\00idamax\00\00112\000\001\000\006\00256\000\000", !25, !1, !3, i32 0, null, null, null, null} ; [ DW_TAG_subprogram ] +!1 = !{!"0x29", !25} ; [ DW_TAG_file_type ] +!2 = !{!"0x11\0012\00clang version 2.9 (trunk 127169)\001\00\000\00\000", !25, !8, !8, !8, null, null} ; [ DW_TAG_compile_unit ] +!3 = !{!"0x15\00\000\000\000\000\000\000", !25, !1, null, !4, i32 0} ; [ DW_TAG_subroutine_type ] +!4 = !{!5} +!5 = !{!"0x24\00int\000\0032\0032\000\000\005", null, !2} ; [ DW_TAG_base_type ] +!6 = !{!"0x2e\00dscal\00dscal\00\00206\000\001\000\006\00256\000\000", !25, !1, !7, i32 0, null, null, null, null} ; [ DW_TAG_subprogram ] +!7 = !{!"0x15\00\000\000\000\000\000\000", !25, !1, null, !8, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!8 = !{null} +!9 = !{!"0x2e\00daxpy\00daxpy\00\00230\000\001\000\006\00256\000\000", !25, !1, !7, i32 0, null, null, null, null} ; [ DW_TAG_subprogram ] +!10 = !{!"0x2e\00dgefa\00dgefa\00\00267\000\001\000\006\00256\000\000", !25, !1, !7, null, null, null, null, null} ; [ DW_TAG_subprogram ] [line 267] [def] [scope 0] [dgefa] +!11 = !MDLocation(line: 281, column: 9, scope: !12) +!12 = !{!"0xb\00272\005\0032", !25, !13} ; [ DW_TAG_lexical_block ] +!13 = !{!"0xb\00271\005\0031", !25, !14} ; [ DW_TAG_lexical_block ] +!14 = !{!"0xb\00267\001\0030", !25, !10} ; [ DW_TAG_lexical_block ] +!15 = !MDLocation(line: 271, column: 5, scope: !14) +!16 = !MDLocation(line: 284, column: 10, scope: !17) +!17 = !{!"0xb\00282\009\0033", !25, !12} ; [ DW_TAG_lexical_block ] +!18 = !{double undef} +!19 = !{!"0x100\00temp\00268\000", !14, !1, !20} ; [ DW_TAG_auto_variable ] +!20 = !{!"0x24\00double\000\0064\0064\000\000\004", null, !2} ; [ DW_TAG_base_type ] +!21 = !MDLocation(line: 286, column: 14, scope: !22) +!22 = !{!"0xb\00285\0013\0034", !25, !17} ; [ DW_TAG_lexical_block ] +!23 = !MDLocation(line: 296, column: 13, scope: !17) +!24 = !MDLocation(line: 313, column: 1, scope: !14) +!25 = !{!"/Volumes/Lalgate/work/llvm/projects/llvm-test/SingleSource/Benchmarks/CoyoteBench/lpbench.c", !"/private/tmp"} +!26 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/LICM/hoist-invariant-load.ll b/test/Transforms/LICM/hoist-invariant-load.ll index 1ba94d6b489c..59904bad4ae6 100644 --- a/test/Transforms/LICM/hoist-invariant-load.ll +++ b/test/Transforms/LICM/hoist-invariant-load.ll @@ -37,4 +37,4 @@ for.end: ; preds = %for.cond declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind -!0 = metadata !{} +!0 = !{} diff --git a/test/Transforms/LICM/preheader-safe.ll b/test/Transforms/LICM/preheader-safe.ll new file mode 100644 index 000000000000..260a5f653b77 --- /dev/null +++ b/test/Transforms/LICM/preheader-safe.ll @@ -0,0 +1,69 @@ +; RUN: opt -S -licm < %s | FileCheck %s + +declare void @use_nothrow(i64 %a) nounwind +declare void @use(i64 %a) + +define void @nothrow(i64 %x, i64 %y, i1* %cond) { +; CHECK-LABEL: nothrow +; CHECK-LABEL: entry +; CHECK: %div = udiv i64 %x, %y +; CHECK-LABEL: loop +; CHECK: call void @use_nothrow(i64 %div) +entry: + br label %loop + +loop: ; preds = %entry, %for.inc + %div = udiv i64 %x, %y + call void @use_nothrow(i64 %div) + br label %loop +} +; Negative test +define void @throw_header(i64 %x, i64 %y, i1* %cond) { +; CHECK-LABEL: throw_header +; CHECK-LABEL: loop +; CHECK: %div = udiv i64 %x, %y +; CHECK: call void @use(i64 %div) +entry: + br label %loop + +loop: ; preds = %entry, %for.inc + %div = udiv i64 %x, %y + call void @use(i64 %div) + br label %loop +} + +; The header is known no throw, but the loop is not. We can +; still lift out of the header. +define void @nothrow_header(i64 %x, i64 %y, i1 %cond) { +; CHECK-LABEL: nothrow_header +; CHECK-LABEL: entry +; CHECK: %div = udiv i64 %x, %y +; CHECK-LABEL: loop +; CHECK: call void @use(i64 %div) +entry: + br label %loop +loop: ; preds = %entry, %for.inc + %div = udiv i64 %x, %y + br i1 %cond, label %loop-if, label %exit +loop-if: + call void @use(i64 %div) + br label %loop +exit: + ret void +} +; Negative test - can't move out of throwing block +define void @nothrow_header_neg(i64 %x, i64 %y, i1 %cond) { +; CHECK-LABEL: nothrow_header_neg +; CHECK-LABEL: entry +; CHECK-LABEL: loop +; CHECK: %div = udiv i64 %x, %y +; CHECK: call void @use(i64 %div) +entry: + br label %loop +loop: ; preds = %entry, %for.inc + br label %loop-if +loop-if: + %div = udiv i64 %x, %y + call void @use(i64 %div) + br label %loop +} diff --git a/test/Transforms/LICM/promote-order.ll b/test/Transforms/LICM/promote-order.ll index 86f11fe04435..a189cf22f66b 100644 --- a/test/Transforms/LICM/promote-order.ll +++ b/test/Transforms/LICM/promote-order.ll @@ -36,8 +36,8 @@ for.end: ; preds = %for.cond.for.end_cr ret i32* %r.0.lcssa } -!0 = metadata !{metadata !"minimal TBAA"} -!1 = metadata !{metadata !3, metadata !3, i64 0} -!2 = metadata !{metadata !4, metadata !4, i64 0} -!3 = metadata !{metadata !"float", metadata !0} -!4 = metadata !{metadata !"int", metadata !0} +!0 = !{!"minimal TBAA"} +!1 = !{!3, !3, i64 0} +!2 = !{!4, !4, i64 0} +!3 = !{!"float", !0} +!4 = !{!"int", !0} diff --git a/test/Transforms/LICM/scalar_promote.ll b/test/Transforms/LICM/scalar_promote.ll index d7e7c6e9a316..80afb3c01e9a 100644 --- a/test/Transforms/LICM/scalar_promote.ll +++ b/test/Transforms/LICM/scalar_promote.ll @@ -185,9 +185,9 @@ for.end: ; preds = %for.cond.for.end_cr ; CHECK-NEXT: store i32 %[[LCSSAPHI]], i32* %gi, align 4, !tbaa !0 } -!0 = metadata !{metadata !4, metadata !4, i64 0} -!1 = metadata !{metadata !"omnipotent char", metadata !2} -!2 = metadata !{metadata !"Simple C/C++ TBAA"} -!3 = metadata !{metadata !5, metadata !5, i64 0} -!4 = metadata !{metadata !"int", metadata !1} -!5 = metadata !{metadata !"float", metadata !1} +!0 = !{!4, !4, i64 0} +!1 = !{!"omnipotent char", !2} +!2 = !{!"Simple C/C++ TBAA"} +!3 = !{!5, !5, i64 0} +!4 = !{!"int", !1} +!5 = !{!"float", !1} diff --git a/test/Transforms/LICM/sinking.ll b/test/Transforms/LICM/sinking.ll index ccc9186f7a48..d7a8fcdafcad 100644 --- a/test/Transforms/LICM/sinking.ll +++ b/test/Transforms/LICM/sinking.ll @@ -314,6 +314,84 @@ exit: ret i32 %lcssa } +; Can't sink stores out of exit blocks containing indirectbr instructions +; because loop simplify does not create dedicated exits for such blocks. Test +; that by sinking the store from lab21 to lab22, but not further. +define void @test12() { +; CHECK-LABEL: @test12 + br label %lab4 + +lab4: + br label %lab20 + +lab5: + br label %lab20 + +lab6: + br label %lab4 + +lab7: + br i1 undef, label %lab8, label %lab13 + +lab8: + br i1 undef, label %lab13, label %lab10 + +lab10: + br label %lab7 + +lab13: + ret void + +lab20: + br label %lab21 + +lab21: +; CHECK: lab21: +; CHECK-NOT: store +; CHECK: br i1 false, label %lab21, label %lab22 + store i32 36127957, i32* undef, align 4 + br i1 undef, label %lab21, label %lab22 + +lab22: +; CHECK: lab22: +; CHECK: store +; CHECK-NEXT: indirectbr i8* undef + indirectbr i8* undef, [label %lab5, label %lab6, label %lab7] +} + +; Test that we don't crash when trying to sink stores and there's no preheader +; available (which is used for creating loads that may be used by the SSA +; updater) +define void @test13() { +; CHECK-LABEL: @test13 + br label %lab59 + +lab19: + br i1 undef, label %lab20, label %lab38 + +lab20: + br label %lab60 + +lab21: + br i1 undef, label %lab22, label %lab38 + +lab22: + br label %lab38 + +lab38: + ret void + +lab59: + indirectbr i8* undef, [label %lab60, label %lab38] + +lab60: +; CHECK: lab60: +; CHECK: store +; CHECK-NEXT: indirectbr + store i32 2145244101, i32* undef, align 4 + indirectbr i8* undef, [label %lab21, label %lab19] +} + declare void @f(i32*) declare void @g() diff --git a/test/Transforms/LoadCombine/load-combine-aa.ll b/test/Transforms/LoadCombine/load-combine-aa.ll new file mode 100644 index 000000000000..3542dcebf5e4 --- /dev/null +++ b/test/Transforms/LoadCombine/load-combine-aa.ll @@ -0,0 +1,39 @@ +; RUN: opt -basicaa -load-combine -instcombine -S < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i64 @test1(i32* nocapture readonly noalias %a, i32* nocapture readonly noalias %b) { +; CHECK-LABEL: @test1 + +; CHECK: load i64* +; CHECK: ret i64 + + %load1 = load i32* %a, align 4 + %conv = zext i32 %load1 to i64 + %arrayidx1 = getelementptr inbounds i32* %a, i64 1 + store i32 %load1, i32* %b, align 4 + %load2 = load i32* %arrayidx1, align 4 + %conv2 = zext i32 %load2 to i64 + %shl = shl nuw i64 %conv2, 32 + %add = or i64 %shl, %conv + ret i64 %add +} + +define i64 @test2(i32* nocapture readonly %a, i32* nocapture readonly %b) { +; CHECK-LABEL: @test2 + +; CHECK: load i32* +; CHECK: load i32* +; CHECK: ret i64 + + %load1 = load i32* %a, align 4 + %conv = zext i32 %load1 to i64 + %arrayidx1 = getelementptr inbounds i32* %a, i64 1 + store i32 %load1, i32* %b, align 4 + %load2 = load i32* %arrayidx1, align 4 + %conv2 = zext i32 %load2 to i64 + %shl = shl nuw i64 %conv2, 32 + %add = or i64 %shl, %conv + ret i64 %add +} + diff --git a/test/Transforms/LoadCombine/load-combine-assume.ll b/test/Transforms/LoadCombine/load-combine-assume.ll new file mode 100644 index 000000000000..94f630072add --- /dev/null +++ b/test/Transforms/LoadCombine/load-combine-assume.ll @@ -0,0 +1,44 @@ +; RUN: opt -basicaa -load-combine -instcombine -S < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @llvm.assume(i1) nounwind + +; 'load' before the 'call' gets optimized: +define i64 @test1(i32* nocapture readonly %a, i1 %b) { +; CHECK-LABEL: @test1 + +; CHECK-DAG: load i64* %1, align 4 +; CHECK-DAG: tail call void @llvm.assume(i1 %b) +; CHECK: ret i64 + + %load1 = load i32* %a, align 4 + %conv = zext i32 %load1 to i64 + %arrayidx1 = getelementptr inbounds i32* %a, i64 1 + %load2 = load i32* %arrayidx1, align 4 + tail call void @llvm.assume(i1 %b) + %conv2 = zext i32 %load2 to i64 + %shl = shl nuw i64 %conv2, 32 + %add = or i64 %shl, %conv + ret i64 %add +} + +; 'call' before the 'load' doesn't get optimized: +define i64 @test2(i32* nocapture readonly %a, i1 %b) { +; CHECK-LABEL: @test2 + +; CHECK-DAG: load i64* %1, align 4 +; CHECK-DAG: tail call void @llvm.assume(i1 %b) +; CHECK: ret i64 + + %load1 = load i32* %a, align 4 + %conv = zext i32 %load1 to i64 + %arrayidx1 = getelementptr inbounds i32* %a, i64 1 + tail call void @llvm.assume(i1 %b) + %load2 = load i32* %arrayidx1, align 4 + %conv2 = zext i32 %load2 to i64 + %shl = shl nuw i64 %conv2, 32 + %add = or i64 %shl, %conv + ret i64 %add +} + diff --git a/test/Transforms/LoopIdiom/debug-line.ll b/test/Transforms/LoopIdiom/debug-line.ll index ef4a478d0e85..863df3c72d50 100644 --- a/test/Transforms/LoopIdiom/debug-line.ll +++ b/test/Transforms/LoopIdiom/debug-line.ll @@ -5,8 +5,8 @@ target triple = "x86_64-apple-darwin10.0.0" define void @foo(double* nocapture %a) nounwind ssp { entry: - tail call void @llvm.dbg.value(metadata !{double* %a}, i64 0, metadata !5), !dbg !8 - tail call void @llvm.dbg.value(metadata !9, i64 0, metadata !10), !dbg !14 + tail call void @llvm.dbg.value(metadata double* %a, i64 0, metadata !5, metadata !{}), !dbg !8 + tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !10, metadata !{}), !dbg !14 br label %for.body for.body: ; preds = %entry, %for.body @@ -19,34 +19,34 @@ for.body: ; preds = %entry, %for.body br i1 %exitcond, label %for.body, label %for.end, !dbg !14 for.end: ; preds = %for.body - tail call void @llvm.dbg.value(metadata !{null}, i64 0, metadata !10), !dbg !16 + tail call void @llvm.dbg.value(metadata !{null}, i64 0, metadata !10, metadata !{}), !dbg !16 ret void, !dbg !17 } -declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone -declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone !llvm.module.flags = !{!19} !llvm.dbg.sp = !{!0} -!0 = metadata !{i32 589870, metadata !18, metadata !1, metadata !"foo", metadata !"foo", metadata !"", i32 2, metadata !3, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (double*)* @foo, null, null, null, i32 0} ; [ DW_TAG_subprogram ] [line 2] [def] [scope 0] [foo] -!1 = metadata !{i32 589865, metadata !18} ; [ DW_TAG_file_type ] -!2 = metadata !{i32 589841, metadata !18, i32 12, metadata !"clang version 2.9 (trunk 127165:127174)", i1 true, metadata !"", i32 0, metadata !9, metadata !9, null, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!3 = metadata !{i32 589845, metadata !18, metadata !1, metadata !"", i32 0, i64 0, i64 0, i32 0, i32 0, null, metadata !4, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!4 = metadata !{null} -!5 = metadata !{i32 590081, metadata !0, metadata !"a", metadata !1, i32 16777218, metadata !6, i32 0} ; [ DW_TAG_arg_variable ] -!6 = metadata !{i32 589839, null, metadata !2, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !7} ; [ DW_TAG_pointer_type ] -!7 = metadata !{i32 589860, null, metadata !2, metadata !"double", i32 0, i64 64, i64 64, i64 0, i32 0, i32 4} ; [ DW_TAG_base_type ] -!8 = metadata !{i32 2, i32 18, metadata !0, null} -!9 = metadata !{i32 0} -!10 = metadata !{i32 590080, metadata !11, metadata !"i", metadata !1, i32 3, metadata !13, i32 0} ; [ DW_TAG_auto_variable ] -!11 = metadata !{i32 589835, metadata !18, metadata !12, i32 3, i32 3, i32 1} ; [ DW_TAG_lexical_block ] -!12 = metadata !{i32 589835, metadata !18, metadata !0, i32 2, i32 21, i32 0} ; [ DW_TAG_lexical_block ] -!13 = metadata !{i32 589860, null, metadata !2, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!14 = metadata !{i32 3, i32 3, metadata !12, null} -!15 = metadata !{i32 4, i32 5, metadata !11, null} -!16 = metadata !{i32 3, i32 29, metadata !11, null} -!17 = metadata !{i32 5, i32 1, metadata !12, null} -!18 = metadata !{metadata !"li.c", metadata !"/private/tmp"} -!19 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x2e\00foo\00foo\00\002\000\001\000\006\00256\000\000", !18, !1, !3, null, void (double*)* @foo, null, null, null} ; [ DW_TAG_subprogram ] [line 2] [def] [scope 0] [foo] +!1 = !{!"0x29", !18} ; [ DW_TAG_file_type ] +!2 = !{!"0x11\0012\00clang version 2.9 (trunk 127165:127174)\001\00\000\00\000", !18, !9, !9, null, null, null} ; [ DW_TAG_compile_unit ] +!3 = !{!"0x15\00\000\000\000\000\000\000", !18, !1, null, !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!4 = !{null} +!5 = !{!"0x101\00a\0016777218\000", !0, !1, !6} ; [ DW_TAG_arg_variable ] +!6 = !{!"0xf\00\000\0064\0064\000\000", null, !2, !7} ; [ DW_TAG_pointer_type ] +!7 = !{!"0x24\00double\000\0064\0064\000\000\004", null, !2} ; [ DW_TAG_base_type ] +!8 = !MDLocation(line: 2, column: 18, scope: !0) +!9 = !{i32 0} +!10 = !{!"0x100\00i\003\000", !11, !1, !13} ; [ DW_TAG_auto_variable ] +!11 = !{!"0xb\003\003\001", !18, !12} ; [ DW_TAG_lexical_block ] +!12 = !{!"0xb\002\0021\000", !18, !0} ; [ DW_TAG_lexical_block ] +!13 = !{!"0x24\00int\000\0032\0032\000\000\005", null, !2} ; [ DW_TAG_base_type ] +!14 = !MDLocation(line: 3, column: 3, scope: !12) +!15 = !MDLocation(line: 4, column: 5, scope: !11) +!16 = !MDLocation(line: 3, column: 29, scope: !11) +!17 = !MDLocation(line: 5, column: 1, scope: !12) +!18 = !{!"li.c", !"/private/tmp"} +!19 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/LoopRotate/dbgvalue.ll b/test/Transforms/LoopRotate/dbgvalue.ll index 50fc9659a804..846b366f2942 100644 --- a/test/Transforms/LoopRotate/dbgvalue.ll +++ b/test/Transforms/LoopRotate/dbgvalue.ll @@ -1,12 +1,12 @@ ; RUN: opt -S -loop-rotate < %s | FileCheck %s -declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone -declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone define i32 @tak(i32 %x, i32 %y, i32 %z) nounwind ssp { ; CHECK-LABEL: define i32 @tak( ; CHECK: entry -; CHECK-NEXT: call void @llvm.dbg.value(metadata !{i32 %x} +; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 %x entry: br label %tailrecurse @@ -15,9 +15,9 @@ tailrecurse: ; preds = %if.then, %entry %x.tr = phi i32 [ %x, %entry ], [ %call, %if.then ] %y.tr = phi i32 [ %y, %entry ], [ %call9, %if.then ] %z.tr = phi i32 [ %z, %entry ], [ %call14, %if.then ] - tail call void @llvm.dbg.value(metadata !{i32 %x.tr}, i64 0, metadata !6), !dbg !7 - tail call void @llvm.dbg.value(metadata !{i32 %y.tr}, i64 0, metadata !8), !dbg !9 - tail call void @llvm.dbg.value(metadata !{i32 %z.tr}, i64 0, metadata !10), !dbg !11 + tail call void @llvm.dbg.value(metadata i32 %x.tr, i64 0, metadata !6, metadata !{}), !dbg !7 + tail call void @llvm.dbg.value(metadata i32 %y.tr, i64 0, metadata !8, metadata !{}), !dbg !9 + tail call void @llvm.dbg.value(metadata i32 %z.tr, i64 0, metadata !10, metadata !{}), !dbg !11 %cmp = icmp slt i32 %y.tr, %x.tr, !dbg !12 br i1 %cmp, label %if.then, label %if.end, !dbg !12 @@ -46,9 +46,9 @@ define void @FindFreeHorzSeg(i64 %startCol, i64 %row, i64* %rowStart) { ; CHECK-LABEL: define void @FindFreeHorzSeg( ; CHECK: %dec = add ; CHECK-NEXT: tail call void @llvm.dbg.value -; CHECK-NEXT: br i1 %tobool, label %for.cond, label %[[LOOP_EXIT:[^,]*]] -; CHECK: [[LOOP_EXIT]]: -; CHECK-NEXT: phi i64 [ %{{[^,]*}}, %{{[^,]*}} ] +; CHECK: %cmp = icmp +; CHECK: br i1 %cmp +; CHECK: phi i64 [ %{{[^,]*}}, %{{[^,]*}} ] ; CHECK-NEXT: br label %for.end @@ -72,7 +72,7 @@ for.body: for.inc: %dec = add i64 %i.0, -1 - tail call void @llvm.dbg.value(metadata !{i64 %dec}, i64 0, metadata !{metadata !"undef"}) + tail call void @llvm.dbg.value(metadata i64 %dec, i64 0, metadata !{!"undef"}, metadata !{}) br label %for.cond for.end: @@ -84,24 +84,24 @@ for.end: !llvm.module.flags = !{!20} !llvm.dbg.sp = !{!0} -!0 = metadata !{i32 589870, metadata !18, metadata !1, metadata !"tak", metadata !"tak", metadata !"", i32 32, metadata !3, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32, i32, i32)* @tak, null, null, null, i32 0} ; [ DW_TAG_subprogram ] [line 32] [def] [scope 0] [tak] -!1 = metadata !{i32 589865, metadata !18} ; [ DW_TAG_file_type ] -!2 = metadata !{i32 589841, metadata !18, i32 12, metadata !"clang version 2.9 (trunk 125492)", i1 true, metadata !"", i32 0, metadata !19, metadata !19, null, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!3 = metadata !{i32 589845, metadata !18, metadata !1, metadata !"", i32 0, i64 0, i64 0, i32 0, i32 0, null, metadata !4, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!4 = metadata !{metadata !5} -!5 = metadata !{i32 589860, null, metadata !2, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!6 = metadata !{i32 590081, metadata !0, metadata !"x", metadata !1, i32 32, metadata !5, i32 0} ; [ DW_TAG_arg_variable ] -!7 = metadata !{i32 32, i32 13, metadata !0, null} -!8 = metadata !{i32 590081, metadata !0, metadata !"y", metadata !1, i32 32, metadata !5, i32 0} ; [ DW_TAG_arg_variable ] -!9 = metadata !{i32 32, i32 20, metadata !0, null} -!10 = metadata !{i32 590081, metadata !0, metadata !"z", metadata !1, i32 32, metadata !5, i32 0} ; [ DW_TAG_arg_variable ] -!11 = metadata !{i32 32, i32 27, metadata !0, null} -!12 = metadata !{i32 33, i32 3, metadata !13, null} -!13 = metadata !{i32 589835, metadata !18, metadata !0, i32 32, i32 30, i32 6} ; [ DW_TAG_lexical_block ] -!14 = metadata !{i32 34, i32 5, metadata !15, null} -!15 = metadata !{i32 589835, metadata !18, metadata !13, i32 33, i32 14, i32 7} ; [ DW_TAG_lexical_block ] -!16 = metadata !{i32 36, i32 3, metadata !13, null} -!17 = metadata !{i32 37, i32 1, metadata !13, null} -!18 = metadata !{metadata !"/Volumes/Lalgate/cj/llvm/projects/llvm-test/SingleSource/Benchmarks/BenchmarkGame/recursive.c", metadata !"/Volumes/Lalgate/cj/D/projects/llvm-test/SingleSource/Benchmarks/BenchmarkGame"} -!19 = metadata !{i32 0} -!20 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x2e\00tak\00tak\00\0032\000\001\000\006\00256\000\000", !18, !1, !3, null, i32 (i32, i32, i32)* @tak, null, null, null} ; [ DW_TAG_subprogram ] [line 32] [def] [scope 0] [tak] +!1 = !{!"0x29", !18} ; [ DW_TAG_file_type ] +!2 = !{!"0x11\0012\00clang version 2.9 (trunk 125492)\001\00\000\00\000", !18, !19, !19, null, null, null} ; [ DW_TAG_compile_unit ] +!3 = !{!"0x15\00\000\000\000\000\000\000", !18, !1, null, !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!4 = !{!5} +!5 = !{!"0x24\00int\000\0032\0032\000\000\005", null, !2} ; [ DW_TAG_base_type ] +!6 = !{!"0x101\00x\0032\000", !0, !1, !5} ; [ DW_TAG_arg_variable ] +!7 = !MDLocation(line: 32, column: 13, scope: !0) +!8 = !{!"0x101\00y\0032\000", !0, !1, !5} ; [ DW_TAG_arg_variable ] +!9 = !MDLocation(line: 32, column: 20, scope: !0) +!10 = !{!"0x101\00z\0032\000", !0, !1, !5} ; [ DW_TAG_arg_variable ] +!11 = !MDLocation(line: 32, column: 27, scope: !0) +!12 = !MDLocation(line: 33, column: 3, scope: !13) +!13 = !{!"0xb\0032\0030\006", !18, !0} ; [ DW_TAG_lexical_block ] +!14 = !MDLocation(line: 34, column: 5, scope: !15) +!15 = !{!"0xb\0033\0014\007", !18, !13} ; [ DW_TAG_lexical_block ] +!16 = !MDLocation(line: 36, column: 3, scope: !13) +!17 = !MDLocation(line: 37, column: 1, scope: !13) +!18 = !{!"/Volumes/Lalgate/cj/llvm/projects/llvm-test/SingleSource/Benchmarks/BenchmarkGame/recursive.c", !"/Volumes/Lalgate/cj/D/projects/llvm-test/SingleSource/Benchmarks/BenchmarkGame"} +!19 = !{i32 0} +!20 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/LoopRotate/nosimplifylatch.ll b/test/Transforms/LoopRotate/nosimplifylatch.ll new file mode 100644 index 000000000000..8e858b4dfcc3 --- /dev/null +++ b/test/Transforms/LoopRotate/nosimplifylatch.ll @@ -0,0 +1,34 @@ +; RUN: opt -S < %s -loop-rotate -licm -verify-dom-info -verify-loop-info | FileCheck %s +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "arm64-apple-ios8.0.0" + +;CHECK: for.inc: +;CHECK-NEXT: %incdec.ptr.i = getelementptr + +; Function Attrs: alwaysinline inlinehint nounwind readonly ssp +define linkonce_odr hidden i64 @_ZNSt3__14findINS_11__wrap_iterIPiEEiEET_S4_S4_RKT0_(i64 %__first.coerce, i64 %__last.coerce, i32* nocapture readonly dereferenceable(4) %__value_) { +entry: + %coerce.val.ip = inttoptr i64 %__first.coerce to i32* + %coerce.val.ip2 = inttoptr i64 %__last.coerce to i32* + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %coerce.val.ip9 = phi i32* [ %incdec.ptr.i, %for.inc ], [ %coerce.val.ip, %entry ] + %lnot.i = icmp eq i32* %coerce.val.ip9, %coerce.val.ip2 + br i1 %lnot.i, label %for.end, label %for.body + +for.body: ; preds = %for.cond + %0 = load i32* %coerce.val.ip9, align 4 + %1 = load i32* %__value_, align 4 + %cmp = icmp eq i32 %0, %1 + br i1 %cmp, label %for.end, label %for.inc + +for.inc: ; preds = %for.body + %incdec.ptr.i = getelementptr inbounds i32* %coerce.val.ip9, i64 1 + br label %for.cond + +for.end: ; preds = %for.cond, %for.body + %coerce.val.ip9.lcssa = phi i32* [ %coerce.val.ip9, %for.cond ], [ %coerce.val.ip9, %for.body ] + %coerce.val.pi = ptrtoint i32* %coerce.val.ip9.lcssa to i64 + ret i64 %coerce.val.pi +} diff --git a/test/Transforms/LoopRotate/simplifylatch.ll b/test/Transforms/LoopRotate/simplifylatch.ll index d646cb9d6cb2..62e5b1ae11d5 100644 --- a/test/Transforms/LoopRotate/simplifylatch.ll +++ b/test/Transforms/LoopRotate/simplifylatch.ll @@ -4,7 +4,7 @@ @mode_table = global [4 x i32] zeroinitializer ; <[4 x i32]*> [#uses=1] ; CHECK-LABEL: @f( -; CHECK-NOT: bb4 +; CHECK-NOT: bb: define i8 @f() { entry: tail call i32 @fegetround( ) ; <i32>:0 [#uses=1] diff --git a/test/Transforms/LoopSimplify/merge-exits.ll b/test/Transforms/LoopSimplify/merge-exits.ll index 8de5938939dc..9678148c3570 100644 --- a/test/Transforms/LoopSimplify/merge-exits.ll +++ b/test/Transforms/LoopSimplify/merge-exits.ll @@ -1,6 +1,4 @@ -; RUN: opt < %s -loop-simplify -loop-rotate -instcombine -indvars -S -verify-loop-info -verify-dom-info > %t -; RUN: not grep sext %t -; RUN: grep "phi i64" %t | count 1 +; RUN: opt < %s -loop-simplify -loop-rotate -instcombine -indvars -S -verify-loop-info -verify-dom-info | FileCheck %s ; Loopsimplify should be able to merge the two loop exits ; into one, so that loop rotate can rotate the loop, so @@ -9,36 +7,42 @@ 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-n32:64" -define float @t(float* %pTmp1, float* %peakWeight, i32 %bandEdgeIndex) nounwind { +; CHECK-LABEL: @test1 +; CHECK: bb: +; CHECK: phi i64 +; CHECK-NOT: phi i64 +; CHECK-NOT: sext + +define float @test1(float* %pTmp1, float* %peakWeight, i32 %bandEdgeIndex) nounwind { entry: - %t0 = load float* %peakWeight, align 4 ; <float> [#uses=1] + %t0 = load float* %peakWeight, align 4 br label %bb1 bb: ; preds = %bb2 - %t1 = sext i32 %hiPart.0 to i64 ; <i64> [#uses=1] - %t2 = getelementptr float* %pTmp1, i64 %t1 ; <float*> [#uses=1] - %t3 = load float* %t2, align 4 ; <float> [#uses=1] - %t4 = fadd float %t3, %distERBhi.0 ; <float> [#uses=1] - %t5 = add i32 %hiPart.0, 1 ; <i32> [#uses=2] - %t6 = sext i32 %t5 to i64 ; <i64> [#uses=1] - %t7 = getelementptr float* %peakWeight, i64 %t6 ; <float*> [#uses=1] - %t8 = load float* %t7, align 4 ; <float> [#uses=1] - %t9 = fadd float %t8, %peakCount.0 ; <float> [#uses=1] + %t1 = sext i32 %hiPart.0 to i64 + %t2 = getelementptr float* %pTmp1, i64 %t1 + %t3 = load float* %t2, align 4 + %t4 = fadd float %t3, %distERBhi.0 + %t5 = add i32 %hiPart.0, 1 + %t6 = sext i32 %t5 to i64 + %t7 = getelementptr float* %peakWeight, i64 %t6 + %t8 = load float* %t7, align 4 + %t9 = fadd float %t8, %peakCount.0 br label %bb1 bb1: ; preds = %bb, %entry - %peakCount.0 = phi float [ %t0, %entry ], [ %t9, %bb ] ; <float> [#uses=2] - %hiPart.0 = phi i32 [ 0, %entry ], [ %t5, %bb ] ; <i32> [#uses=3] - %distERBhi.0 = phi float [ 0.000000e+00, %entry ], [ %t4, %bb ] ; <float> [#uses=3] - %t10 = fcmp uge float %distERBhi.0, 2.500000e+00 ; <i1> [#uses=1] + %peakCount.0 = phi float [ %t0, %entry ], [ %t9, %bb ] + %hiPart.0 = phi i32 [ 0, %entry ], [ %t5, %bb ] + %distERBhi.0 = phi float [ 0.000000e+00, %entry ], [ %t4, %bb ] + %t10 = fcmp uge float %distERBhi.0, 2.500000e+00 br i1 %t10, label %bb3, label %bb2 bb2: ; preds = %bb1 - %t11 = add i32 %bandEdgeIndex, -1 ; <i32> [#uses=1] - %t12 = icmp sgt i32 %t11, %hiPart.0 ; <i1> [#uses=1] + %t11 = add i32 %bandEdgeIndex, -1 + %t12 = icmp sgt i32 %t11, %hiPart.0 br i1 %t12, label %bb, label %bb3 bb3: ; preds = %bb2, %bb1 - %t13 = fdiv float %peakCount.0, %distERBhi.0 ; <float> [#uses=1] + %t13 = fdiv float %peakCount.0, %distERBhi.0 ret float %t13 } diff --git a/test/Transforms/LoopStrengthReduce/AArch64/lsr-memset.ll b/test/Transforms/LoopStrengthReduce/AArch64/lsr-memset.ll index 10b2c3a403cc..48b709429467 100644 --- a/test/Transforms/LoopStrengthReduce/AArch64/lsr-memset.ll +++ b/test/Transforms/LoopStrengthReduce/AArch64/lsr-memset.ll @@ -96,6 +96,6 @@ done: ; preds = %while.cond, %while. ret i8* %dest } -!0 = metadata !{metadata !"omnipotent char", metadata !1} -!1 = metadata !{metadata !"Simple C/C++ TBAA"} -!2 = metadata !{metadata !"long long", metadata !0} +!0 = !{!"omnipotent char", !1} +!1 = !{!"Simple C/C++ TBAA"} +!2 = !{!"long long", !0} diff --git a/test/Transforms/LoopStrengthReduce/ARM/ivchain-ARM.ll b/test/Transforms/LoopStrengthReduce/ARM/ivchain-ARM.ll index f4edf092641f..26b294042d42 100644 --- a/test/Transforms/LoopStrengthReduce/ARM/ivchain-ARM.ll +++ b/test/Transforms/LoopStrengthReduce/ARM/ivchain-ARM.ll @@ -201,7 +201,7 @@ for.end: ; preds = %for.body ; ; Currently we have three extra add.w's that keep the store address ; live past the next increment because ISEL is unfortunately undoing -; the store chain. ISEL also fails to convert the stores to +; the store chain. ISEL also fails to convert all but one of the stores to ; post-increment addressing. However, the loads should use ; post-increment addressing, no add's or add.w's beyond the three ; mentioned. Most importantly, there should be no spills or reloads! @@ -210,7 +210,7 @@ for.end: ; preds = %for.body ; A9: %.lr.ph ; A9-NOT: lsl.w ; A9-NOT: {{ldr|str|adds|add r}} -; A9: add.w r +; A9: vst1.8 {{.*}} [r{{[0-9]+}}]! ; A9-NOT: {{ldr|str|adds|add r}} ; A9: add.w r ; A9-NOT: {{ldr|str|adds|add r}} diff --git a/test/Transforms/LoopStrengthReduce/pr12018.ll b/test/Transforms/LoopStrengthReduce/pr12018.ll index ee7b1e8883e6..e493cf85fdef 100644 --- a/test/Transforms/LoopStrengthReduce/pr12018.ll +++ b/test/Transforms/LoopStrengthReduce/pr12018.ll @@ -16,7 +16,7 @@ for.body: ; preds = %_ZN8nsTArray9Elemen %tmp = bitcast %struct.nsTArrayHeader* %add.ptr.i to %struct.nsTArray* %arrayidx = getelementptr inbounds %struct.nsTArray* %tmp, i32 %i.06 %add = add nsw i32 %i.06, 1 - call void @llvm.dbg.value(metadata !{%struct.nsTArray* %aValues}, i64 0, metadata !0) nounwind + call void @llvm.dbg.value(metadata %struct.nsTArray* %aValues, i64 0, metadata !0, metadata !{}) nounwind br label %_ZN8nsTArray9ElementAtEi.exit _ZN8nsTArray9ElementAtEi.exit: ; preds = %for.body @@ -33,6 +33,6 @@ declare void @_ZN11nsTArray15ComputeDistanceERKS_Rd(%struct.nsTArray*, %struct.n declare %struct.nsTArrayHeader* @_ZN8nsTArray4Hdr2Ev() -declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone -!0 = metadata !{i32 786689} ; [ DW_TAG_arg_variable ] +!0 = !{!"0x101"} ; [ DW_TAG_arg_variable ] diff --git a/test/Transforms/LoopStrengthReduce/pr18165.ll b/test/Transforms/LoopStrengthReduce/pr18165.ll index c38d6a625e88..cc878c48c4b9 100644 --- a/test/Transforms/LoopStrengthReduce/pr18165.ll +++ b/test/Transforms/LoopStrengthReduce/pr18165.ll @@ -77,12 +77,12 @@ attributes #2 = { nounwind optsize } !llvm.ident = !{!0} -!0 = metadata !{metadata !"clang version 3.5 "} -!1 = metadata !{metadata !2, metadata !3, i64 0} -!2 = metadata !{metadata !"", metadata !3, i64 0, metadata !3, i64 4, metadata !3, i64 8} -!3 = metadata !{metadata !"int", metadata !4, i64 0} -!4 = metadata !{metadata !"omnipotent char", metadata !5, i64 0} -!5 = metadata !{metadata !"Simple C/C++ TBAA"} -!6 = metadata !{metadata !2, metadata !3, i64 8} -!7 = metadata !{metadata !3, metadata !3, i64 0} -!8 = metadata !{metadata !2, metadata !3, i64 4} +!0 = !{!"clang version 3.5 "} +!1 = !{!2, !3, i64 0} +!2 = !{!"", !3, i64 0, !3, i64 4, !3, i64 8} +!3 = !{!"int", !4, i64 0} +!4 = !{!"omnipotent char", !5, i64 0} +!5 = !{!"Simple C/C++ TBAA"} +!6 = !{!2, !3, i64 8} +!7 = !{!3, !3, i64 0} +!8 = !{!2, !3, i64 4} diff --git a/test/Transforms/LoopUnroll/PowerPC/a2-unrolling.ll b/test/Transforms/LoopUnroll/PowerPC/a2-unrolling.ll index 17c91e5c07b1..aae79cbac789 100644 --- a/test/Transforms/LoopUnroll/PowerPC/a2-unrolling.ll +++ b/test/Transforms/LoopUnroll/PowerPC/a2-unrolling.ll @@ -41,8 +41,7 @@ for.end: ; preds = %for.body, %entry } ; CHECK-LABEL: @test -; CHECK: unr.cmp{{.*}}: -; CHECK: for.body.unr{{.*}}: +; CHECK: for.body.prol{{.*}}: ; CHECK: for.body: ; CHECK: br i1 %exitcond.7, label %for.end.loopexit{{.*}}, label %for.body diff --git a/test/Transforms/LoopUnroll/PowerPC/p7-unrolling.ll b/test/Transforms/LoopUnroll/PowerPC/p7-unrolling.ll new file mode 100644 index 000000000000..7a50fc0a4f49 --- /dev/null +++ b/test/Transforms/LoopUnroll/PowerPC/p7-unrolling.ll @@ -0,0 +1,99 @@ +; RUN: opt < %s -S -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 -loop-unroll | FileCheck %s +define void @unroll_opt_for_size() nounwind optsize { +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %inc, %loop ] + %inc = add i32 %iv, 1 + %exitcnd = icmp uge i32 %inc, 1024 + br i1 %exitcnd, label %exit, label %loop + +exit: + ret void +} + +; CHECK-LABEL: @unroll_opt_for_size +; CHECK: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: icmp + +define void @unroll_default() nounwind { +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %inc, %loop ] + %inc = add i32 %iv, 1 + %exitcnd = icmp uge i32 %inc, 1024 + br i1 %exitcnd, label %exit, label %loop + +exit: + ret void +} + +; CHECK-LABEL: @unroll_default +; CHECK: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: icmp + diff --git a/test/Transforms/LoopUnroll/ephemeral.ll b/test/Transforms/LoopUnroll/ephemeral.ll new file mode 100644 index 000000000000..9d4061390537 --- /dev/null +++ b/test/Transforms/LoopUnroll/ephemeral.ll @@ -0,0 +1,44 @@ +; RUN: opt < %s -S -loop-unroll -unroll-threshold=50 | FileCheck %s + +; Make sure this loop is completely unrolled... +; CHECK-LABEL: @test1 +; CHECK: for.body: +; CHECK-NOT: for.end: + +define i32 @test1(i32* nocapture %a) nounwind uwtable readonly { +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %sum.01 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + + ; This loop will be completely unrolled, even with these extra instructions, + ; but only because they're ephemeral (and, thus, free). + %1 = add nsw i32 %0, 2 + %2 = add nsw i32 %1, 4 + %3 = add nsw i32 %2, 4 + %4 = add nsw i32 %3, 4 + %5 = add nsw i32 %4, 4 + %6 = add nsw i32 %5, 4 + %7 = add nsw i32 %6, 4 + %8 = add nsw i32 %7, 4 + %9 = add nsw i32 %8, 4 + %10 = add nsw i32 %9, 4 + %ca = icmp sgt i32 %10, -7 + call void @llvm.assume(i1 %ca) + + %add = add nsw i32 %0, %sum.01 + %indvars.iv.next = add i64 %indvars.iv, 1 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32 + %exitcond = icmp eq i32 %lftr.wideiv, 5 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret i32 %add +} + +declare void @llvm.assume(i1) nounwind + diff --git a/test/Transforms/LoopUnroll/ignore-annotation-intrinsic-cost.ll b/test/Transforms/LoopUnroll/ignore-annotation-intrinsic-cost.ll new file mode 100644 index 000000000000..dcb5d1c28fb2 --- /dev/null +++ b/test/Transforms/LoopUnroll/ignore-annotation-intrinsic-cost.ll @@ -0,0 +1,133 @@ +; REQUIRES: asserts +; RUN: opt < %s -disable-output -stats -loop-unroll -info-output-file - | FileCheck %s --check-prefix=STATS +; STATS: 1 loop-unroll - Number of loops unrolled (completely or otherwise) +; Test that llvm.annotation intrinsic do not count against the loop body size +; and prevent unrolling. +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64" + +@B = common global i32 0, align 4 + +define void @foo(i32* noalias %A, i32 %B, i32 %C) { +entry: + br label %for.body + +; A loop that has a small loop body (except for the annotations) that should be +; unrolled with the default heuristic. Make sure the extra annotations do not +; prevent unrolling +for.body: ; preds = %entry, %for.body + %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ] + ; The real loop. + %mul = mul nsw i32 %B, %C + %arrayidx = getelementptr inbounds i32* %A, i32 %i.01 + store i32 %mul, i32* %arrayidx, align 4 + %inc = add nsw i32 %i.01, 1 + %exitcond = icmp ne i32 %inc, 4 + + ; A bunch of annotations + %annot.0 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.1 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.2 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.3 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.4 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.5 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.6 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.7 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.8 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.9 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.10 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.11 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.12 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.13 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.14 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.15 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.16 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.17 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.18 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.19 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.20 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.21 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.22 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.23 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.24 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.25 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.26 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.27 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.28 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.29 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.30 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.31 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.32 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.33 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.34 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.35 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.36 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.37 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.38 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.39 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.40 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.41 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.42 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.43 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.44 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.45 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.46 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.47 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.48 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.49 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.50 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.51 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.52 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.53 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.54 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.55 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.56 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.57 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.58 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.59 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.60 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.61 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.62 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.63 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.64 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.65 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.66 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.67 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.68 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.69 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.70 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.71 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.72 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.73 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.74 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.75 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.76 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.77 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.78 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.79 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.80 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.81 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.82 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.83 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.84 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.85 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.86 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.87 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.88 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.89 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.90 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.91 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.92 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.93 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.94 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.95 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.96 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.97 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.98 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + %annot.99 = tail call i32 @llvm.annotation.i32(i32 %i.01, i8* null, i8* null, i32 0) + br i1 %exitcond, label %for.body, label %for.end + +for.end: ; preds = %for.body + ret void +} + +declare i32 @llvm.annotation.i32(i32, i8*, i8*, i32) diff --git a/test/Transforms/LoopUnroll/nsw-tripcount.ll b/test/Transforms/LoopUnroll/nsw-tripcount.ll new file mode 100644 index 000000000000..98cab32a42a6 --- /dev/null +++ b/test/Transforms/LoopUnroll/nsw-tripcount.ll @@ -0,0 +1,32 @@ +; RUN: opt -loop-unroll -S %s | FileCheck %s + +; extern void f(int); +; void test1(int v) { +; for (int i=v; i<=v+1; ++i) +; f(i); +; } +; +; We can use the nsw information to see that the tripcount will be 2, so the +; loop should be unrolled as this is always beneficial + +declare void @f(i32) + +; CHECK-LABEL: @test1 +define void @test1(i32 %v) { +entry: + %add = add nsw i32 %v, 1 + br label %for.body + +for.body: + %i.04 = phi i32 [ %v, %entry ], [ %inc, %for.body ] + tail call void @f(i32 %i.04) + %inc = add nsw i32 %i.04, 1 + %cmp = icmp slt i32 %i.04, %add + br i1 %cmp, label %for.body, label %for.end + +; CHECK: call void @f +; CHECK-NOT: br i1 +; CHECK: call void @f +for.end: + ret void +} diff --git a/test/Transforms/LoopUnroll/partial-unroll-optsize.ll b/test/Transforms/LoopUnroll/partial-unroll-optsize.ll index 3179d55e978a..a650317f3df7 100644 --- a/test/Transforms/LoopUnroll/partial-unroll-optsize.ll +++ b/test/Transforms/LoopUnroll/partial-unroll-optsize.ll @@ -1,7 +1,7 @@ ; RUN: opt < %s -S -loop-unroll -unroll-allow-partial | FileCheck %s ; Loop size = 3, when the function has the optsize attribute, the ; OptSizeUnrollThreshold, i.e. 50, is used, hence the loop should be unrolled -; by 16 times because 3 * 16 < 50. +; by 32 times because (1 * 32) + 2 < 50 (whereas (1 * 64 + 2) is not). define void @unroll_opt_for_size() nounwind optsize { entry: br label %loop @@ -32,4 +32,21 @@ exit: ; CHECK-NEXT: add ; CHECK-NEXT: add ; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: add ; CHECK-NEXT: icmp + diff --git a/test/Transforms/LoopUnroll/runtime-loop.ll b/test/Transforms/LoopUnroll/runtime-loop.ll index a14087dcdce7..3a8777bb1473 100644 --- a/test/Transforms/LoopUnroll/runtime-loop.ll +++ b/test/Transforms/LoopUnroll/runtime-loop.ll @@ -3,15 +3,16 @@ ; Tests for unrolling loops with run-time trip counts ; CHECK: %xtraiter = and i32 %n -; CHECK: %lcmp.mod = icmp ne i32 %xtraiter, 0 -; CHECK: %lcmp.overflow = icmp eq i32 %n, 0 -; CHECK: %lcmp.or = or i1 %lcmp.overflow, %lcmp.mod -; CHECK: br i1 %lcmp.or, label %unr.cmp +; CHECK: %lcmp.mod = icmp ne i32 %xtraiter, 0 +; CHECK: %lcmp.overflow = icmp eq i32 %n, 0 +; CHECK: %lcmp.or = or i1 %lcmp.overflow, %lcmp.mod +; CHECK: br i1 %lcmp.or, label %for.body.prol, label %for.body.preheader.split -; CHECK: unr.cmp{{.*}}: -; CHECK: for.body.unr{{.*}}: -; CHECK: for.body: -; CHECK: br i1 %exitcond.7, label %for.end.loopexit{{.*}}, label %for.body +; CHECK: for.body.prol: +; CHECK: %indvars.iv.prol = phi i64 [ %indvars.iv.next.prol, %for.body.prol ], [ 0, %for.body.preheader ] +; CHECK: %prol.iter.sub = sub i32 %prol.iter, 1 +; CHECK: %prol.iter.cmp = icmp ne i32 %prol.iter.sub, 0 +; CHECK: br i1 %prol.iter.cmp, label %for.body.prol, label %for.body.preheader.split, !llvm.loop !0 define i32 @test(i32* nocapture %a, i32 %n) nounwind uwtable readonly { entry: @@ -39,7 +40,7 @@ for.end: ; preds = %for.body, %entry ; even if the -unroll-runtime is specified ; CHECK: for.body: -; CHECK-NOT: for.body.unr: +; CHECK-NOT: for.body.prol: define i32 @test1(i32* nocapture %a) nounwind uwtable readonly { entry: @@ -85,8 +86,8 @@ cond_true138: ; Test run-time unrolling for a loop that counts down by -2. -; CHECK: for.body.unr: -; CHECK: br i1 %cmp.7, label %for.cond.for.end_crit_edge{{.*}}, label %for.body +; CHECK: for.body.prol: +; CHECK: br i1 %prol.iter.cmp, label %for.body.prol, label %for.body.preheader.split define zeroext i16 @down(i16* nocapture %p, i32 %len) nounwind uwtable readonly { entry: @@ -113,3 +114,7 @@ for.end: ; preds = %for.cond.for.end_cr %res.0.lcssa = phi i16 [ %phitmp, %for.cond.for.end_crit_edge ], [ 0, %entry ] ret i16 %res.0.lcssa } + +; CHECK: !0 = distinct !{!0, !1} +; CHECK: !1 = !{!"llvm.loop.unroll.disable"} + diff --git a/test/Transforms/LoopUnroll/runtime-loop1.ll b/test/Transforms/LoopUnroll/runtime-loop1.ll index ad99b8cd9c66..38b4f32354a3 100644 --- a/test/Transforms/LoopUnroll/runtime-loop1.ll +++ b/test/Transforms/LoopUnroll/runtime-loop1.ll @@ -1,11 +1,11 @@ -; RUN: opt < %s -S -loop-unroll -unroll-runtime -unroll-count=4 | FileCheck %s +; RUN: opt < %s -S -loop-unroll -unroll-runtime -unroll-count=2 | FileCheck %s ; This tests that setting the unroll count works -; CHECK: unr.cmp: -; CHECK: for.body.unr: +; CHECK: for.body.prol: +; CHECK: br i1 %prol.iter.cmp, label %for.body.prol, label %for.body.preheader.split ; CHECK: for.body: -; CHECK: br i1 %exitcond.3, label %for.end.loopexit{{.*}}, label %for.body +; CHECK: br i1 %exitcond.1, label %for.end.loopexit.unr-lcssa, label %for.body ; CHECK-NOT: br i1 %exitcond.4, label %for.end.loopexit{{.*}}, label %for.body define i32 @test(i32* nocapture %a, i32 %n) nounwind uwtable readonly { diff --git a/test/Transforms/LoopUnroll/runtime-loop2.ll b/test/Transforms/LoopUnroll/runtime-loop2.ll index cbc7af58ff5b..176362a34456 100644 --- a/test/Transforms/LoopUnroll/runtime-loop2.ll +++ b/test/Transforms/LoopUnroll/runtime-loop2.ll @@ -1,10 +1,9 @@ -; RUN: opt < %s -S -loop-unroll -unroll-threshold=50 -unroll-runtime -unroll-count=8 | FileCheck %s +; RUN: opt < %s -S -loop-unroll -unroll-threshold=25 -unroll-runtime -unroll-count=8 | FileCheck %s ; Choose a smaller, power-of-two, unroll count if the loop is too large. ; This test makes sure we're not unrolling 'odd' counts -; CHECK: unr.cmp: -; CHECK: for.body.unr: +; CHECK: for.body.prol: ; CHECK: for.body: ; CHECK: br i1 %exitcond.3, label %for.end.loopexit{{.*}}, label %for.body ; CHECK-NOT: br i1 %exitcond.4, label %for.end.loopexit{{.*}}, label %for.body diff --git a/test/Transforms/LoopUnroll/scevunroll.ll b/test/Transforms/LoopUnroll/scevunroll.ll index c3086e8335f9..20161d798e9e 100644 --- a/test/Transforms/LoopUnroll/scevunroll.ll +++ b/test/Transforms/LoopUnroll/scevunroll.ll @@ -66,16 +66,13 @@ exit2: ; SCEV properly unrolls multi-exit loops. ; -; SCEV cannot currently unroll this loop. -; It should ideally detect a trip count of 5. -; rdar:14038809 [SCEV]: Optimize trip count computation for multi-exit loops. ; CHECK-LABEL: @multiExit( -; CHECKFIXME: getelementptr i32* %base, i32 10 -; CHECKFIXME-NEXT: load i32* -; CHECKFIXME: br i1 false, label %l2.10, label %exit1 -; CHECKFIXME: l2.10: -; CHECKFIXME-NOT: br -; CHECKFIXME: ret i32 +; CHECK: getelementptr i32* %base, i32 10 +; CHECK-NEXT: load i32* +; CHECK: br i1 false, label %l2.10, label %exit1 +; CHECK: l2.10: +; CHECK-NOT: br +; CHECK: ret i32 define i32 @multiExit(i32* %base) nounwind { entry: br label %l1 diff --git a/test/Transforms/LoopUnroll/tripcount-overflow.ll b/test/Transforms/LoopUnroll/tripcount-overflow.ll new file mode 100644 index 000000000000..d59368578ec2 --- /dev/null +++ b/test/Transforms/LoopUnroll/tripcount-overflow.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -S -unroll-runtime -unroll-count=2 -loop-unroll | FileCheck %s +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +; When prologue is fully unrolled, the branch on its end is unconditional. +; Unrolling it is illegal if we can't prove that trip-count+1 doesn't overflow, +; like in this example, where it comes from an argument. +; +; This test is based on an example from here: +; http://stackoverflow.com/questions/23838661/why-is-clang-optimizing-this-code-out +; +; CHECK: while.body.prol: +; CHECK: br i1 +; CHECK: entry.split: + +; Function Attrs: nounwind readnone ssp uwtable +define i32 @foo(i32 %N) #0 { +entry: + br label %while.body + +while.body: ; preds = %while.body, %entry + %i = phi i32 [ 0, %entry ], [ %inc, %while.body ] + %cmp = icmp eq i32 %i, %N + %inc = add i32 %i, 1 + br i1 %cmp, label %while.end, label %while.body + +while.end: ; preds = %while.body + ret i32 %i +} + +attributes #0 = { nounwind readnone ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/test/Transforms/LoopUnroll/unroll-pragmas-disabled.ll b/test/Transforms/LoopUnroll/unroll-pragmas-disabled.ll index 39da7fa70ade..4f934a688be8 100644 --- a/test/Transforms/LoopUnroll/unroll-pragmas-disabled.ll +++ b/test/Transforms/LoopUnroll/unroll-pragmas-disabled.ll @@ -1,19 +1,19 @@ ; RUN: opt < %s -loop-unroll -S | FileCheck %s ; -; Verify that the unrolling pass removes existing loop unrolling metadata +; Verify that the unrolling pass removes existing unroll count metadata ; and adds a disable unrolling node after unrolling is complete. target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" -; #pragma clang loop vectorize(enable) unroll(enable) unroll_count(4) vectorize_width(8) +; #pragma clang loop vectorize(enable) unroll_count(4) vectorize_width(8) ; -; Unroll metadata should be replaces with unroll(disable). Vectorize +; Unroll count metadata should be replaced with unroll(disable). Vectorize ; metadata should be untouched. ; -; CHECK-LABEL: @loop1( +; CHECK-LABEL: @unroll_count_4( ; CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_1:.*]] -define void @loop1(i32* nocapture %a) { +define void @unroll_count_4(i32* nocapture %a) { entry: br label %for.body @@ -30,19 +30,49 @@ for.body: ; preds = %for.body, %entry for.end: ; preds = %for.body ret void } -!1 = metadata !{metadata !1, metadata !2, metadata !3, metadata !4, metadata !5} -!2 = metadata !{metadata !"llvm.loop.vectorize.enable", i1 true} -!3 = metadata !{metadata !"llvm.loop.unroll.enable", i1 true} -!4 = metadata !{metadata !"llvm.loop.unroll.count", i32 4} -!5 = metadata !{metadata !"llvm.loop.vectorize.width", i32 8} +!1 = !{!1, !2, !3, !4} +!2 = !{!"llvm.loop.vectorize.enable", i1 true} +!3 = !{!"llvm.loop.unroll.count", i32 4} +!4 = !{!"llvm.loop.vectorize.width", i32 8} + +; #pragma clang loop unroll(full) +; +; An unroll disable metadata node is only added for the unroll count case. +; In this case, the loop has a full unroll metadata but can't be fully unrolled +; because the trip count is dynamic. The full unroll metadata should remain +; after unrolling. +; +; CHECK-LABEL: @unroll_full( +; CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_2:.*]] +define void @unroll_full(i32* nocapture %a, i32 %b) { +entry: + %cmp3 = icmp sgt i32 %b, 0 + br i1 %cmp3, label %for.body, label %for.end, !llvm.loop !5 + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %inc = add nsw i32 %0, 1 + store i32 %inc, i32* %arrayidx, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32 + %exitcond = icmp eq i32 %lftr.wideiv, %b + br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !5 + +for.end: ; preds = %for.body, %entry + ret void +} +!5 = !{!5, !6} +!6 = !{!"llvm.loop.unroll.full"} ; #pragma clang loop unroll(disable) ; ; Unroll metadata should not change. ; -; CHECK-LABEL: @loop2( -; CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_2:.*]] -define void @loop2(i32* nocapture %a) { +; CHECK-LABEL: @unroll_disable( +; CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_3:.*]] +define void @unroll_disable(i32* nocapture %a) { entry: br label %for.body @@ -54,16 +84,66 @@ for.body: ; preds = %for.body, %entry store i32 %inc, i32* %arrayidx, align 4 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 %exitcond = icmp eq i64 %indvars.iv.next, 64 - br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !6 + br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !7 for.end: ; preds = %for.body ret void } -!6 = metadata !{metadata !6, metadata !7} -!7 = metadata !{metadata !"llvm.loop.unroll.enable", i1 false} - -; CHECK: ![[LOOP_1]] = metadata !{metadata ![[LOOP_1]], metadata ![[VEC_ENABLE:.*]], metadata ![[WIDTH_8:.*]], metadata ![[UNROLL_DISABLE:.*]]} -; CHECK: ![[VEC_ENABLE]] = metadata !{metadata !"llvm.loop.vectorize.enable", i1 true} -; CHECK: ![[WIDTH_8]] = metadata !{metadata !"llvm.loop.vectorize.width", i32 8} -; CHECK: ![[UNROLL_DISABLE]] = metadata !{metadata !"llvm.loop.unroll.enable", i1 false} -; CHECK: ![[LOOP_2]] = metadata !{metadata ![[LOOP_2]], metadata ![[UNROLL_DISABLE:.*]]} +!7 = !{!7, !8} +!8 = !{!"llvm.loop.unroll.disable"} + +; This function contains two loops which share the same llvm.loop metadata node +; with an llvm.loop.unroll.count 2 hint. Both loops should be unrolled. This +; verifies that adding disable metadata to a loop after unrolling doesn't affect +; other loops which previously shared the same llvm.loop metadata. +; +; CHECK-LABEL: @shared_metadata( +; CHECK: store i32 +; CHECK: store i32 +; CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_4:.*]] +; CHECK: store i32 +; CHECK: store i32 +; CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_5:.*]] +define void @shared_metadata(i32* nocapture %List) #0 { +entry: + br label %for.body3 + +for.body3: ; preds = %for.body3, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body3 ] + %arrayidx = getelementptr inbounds i32* %List, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add4 = add nsw i32 %0, 10 + store i32 %add4, i32* %arrayidx, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond = icmp eq i64 %indvars.iv.next, 4 + br i1 %exitcond, label %for.body3.1.preheader, label %for.body3, !llvm.loop !9 + +for.body3.1.preheader: ; preds = %for.body3 + br label %for.body3.1 + +for.body3.1: ; preds = %for.body3.1.preheader, %for.body3.1 + %indvars.iv.1 = phi i64 [ %1, %for.body3.1 ], [ 0, %for.body3.1.preheader ] + %1 = add nsw i64 %indvars.iv.1, 1 + %arrayidx.1 = getelementptr inbounds i32* %List, i64 %1 + %2 = load i32* %arrayidx.1, align 4 + %add4.1 = add nsw i32 %2, 10 + store i32 %add4.1, i32* %arrayidx.1, align 4 + %exitcond.1 = icmp eq i64 %1, 4 + br i1 %exitcond.1, label %for.inc5.1, label %for.body3.1, !llvm.loop !9 + +for.inc5.1: ; preds = %for.body3.1 + ret void +} +!9 = !{!9, !10} +!10 = !{!"llvm.loop.unroll.count", i32 2} + + +; CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[VEC_ENABLE:.*]], ![[WIDTH_8:.*]], ![[UNROLL_DISABLE:.*]]} +; CHECK: ![[VEC_ENABLE]] = !{!"llvm.loop.vectorize.enable", i1 true} +; CHECK: ![[WIDTH_8]] = !{!"llvm.loop.vectorize.width", i32 8} +; CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} +; CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2]], ![[UNROLL_FULL:.*]]} +; CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"} +; CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNROLL_DISABLE:.*]]} +; CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[UNROLL_DISABLE:.*]]} +; CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[UNROLL_DISABLE:.*]]} diff --git a/test/Transforms/LoopUnroll/unroll-pragmas.ll b/test/Transforms/LoopUnroll/unroll-pragmas.ll index e1b24e44b5ab..d53fa49cc9f5 100644 --- a/test/Transforms/LoopUnroll/unroll-pragmas.ll +++ b/test/Transforms/LoopUnroll/unroll-pragmas.ll @@ -54,12 +54,12 @@ for.body: ; preds = %for.body, %entry for.end: ; preds = %for.body ret void } -!1 = metadata !{metadata !1, metadata !2} -!2 = metadata !{metadata !"llvm.loop.unroll.enable", i1 false} +!1 = !{!1, !2} +!2 = !{!"llvm.loop.unroll.disable"} ; loop64 has a high enough count that it should *not* be unrolled by ; the default unrolling heuristic. It serves as the control for the -; unroll(enable) pragma test loop64_with_.* tests below. +; unroll(full) pragma test loop64_with_.* tests below. ; ; CHECK-LABEL: @loop64( ; CHECK: store i32 @@ -83,7 +83,7 @@ for.end: ; preds = %for.body ret void } -; #pragma clang loop unroll(enable) +; #pragma clang loop unroll(full) ; Loop should be fully unrolled. ; ; CHECK-LABEL: @loop64_with_enable( @@ -105,8 +105,8 @@ for.body: ; preds = %for.body, %entry for.end: ; preds = %for.body ret void } -!3 = metadata !{metadata !3, metadata !4} -!4 = metadata !{metadata !"llvm.loop.unroll.enable", i1 true} +!3 = !{!3, !4} +!4 = !{!"llvm.loop.unroll.full"} ; #pragma clang loop unroll_count(4) ; Loop should be unrolled 4 times. @@ -135,40 +135,10 @@ for.body: ; preds = %for.body, %entry for.end: ; preds = %for.body ret void } -!5 = metadata !{metadata !5, metadata !6} -!6 = metadata !{metadata !"llvm.loop.unroll.count", i32 4} +!5 = !{!5, !6} +!6 = !{!"llvm.loop.unroll.count", i32 4} - -; #pragma clang loop unroll_count(enable) unroll_count(4) -; Loop should be unrolled 4 times. -; -; CHECK-LABEL: @loop64_with_enable_and_count4( -; CHECK: store i32 -; CHECK: store i32 -; CHECK: store i32 -; CHECK: store i32 -; CHECK-NOT: store i32 -; CHECK: br i1 -define void @loop64_with_enable_and_count4(i32* nocapture %a) { -entry: - br label %for.body - -for.body: ; preds = %for.body, %entry - %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] - %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv - %0 = load i32* %arrayidx, align 4 - %inc = add nsw i32 %0, 1 - store i32 %inc, i32* %arrayidx, align 4 - %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 - %exitcond = icmp eq i64 %indvars.iv.next, 64 - br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !7 - -for.end: ; preds = %for.body - ret void -} -!7 = metadata !{metadata !7, metadata !6, metadata !4} - -; #pragma clang loop unroll_count(enable) +; #pragma clang loop unroll(full) ; Full unrolling is requested, but loop has a dynamic trip count so ; no unrolling should occur. ; @@ -195,7 +165,7 @@ for.body: ; preds = %entry, %for.body for.end: ; preds = %for.body, %entry ret void } -!8 = metadata !{metadata !8, metadata !4} +!8 = !{!8, !4} ; #pragma clang loop unroll_count(4) ; Loop has a dynamic trip count. Unrolling should occur, but no @@ -232,7 +202,7 @@ for.body: ; preds = %entry, %for.body for.end: ; preds = %for.body, %entry ret void } -!9 = metadata !{metadata !9, metadata !6} +!9 = !{!9, !6} ; #pragma clang loop unroll_count(1) ; Loop should not be unrolled @@ -258,10 +228,10 @@ for.body: ; preds = %for.body, %entry for.end: ; preds = %for.body ret void } -!10 = metadata !{metadata !10, metadata !11} -!11 = metadata !{metadata !"llvm.loop.unroll.count", i32 1} +!10 = !{!10, !11} +!11 = !{!"llvm.loop.unroll.count", i32 1} -; #pragma clang loop unroll(enable) +; #pragma clang loop unroll(full) ; Loop has very high loop count (1 million) and full unrolling was requested. ; Loop should unrolled up to the pragma threshold, but not completely. ; @@ -286,4 +256,4 @@ for.body: ; preds = %for.body, %entry for.end: ; preds = %for.body ret void } -!12 = metadata !{metadata !12, metadata !4} +!12 = !{!12, !4} diff --git a/test/Transforms/LoopUnroll/update-loop-info-in-subloops.ll b/test/Transforms/LoopUnroll/update-loop-info-in-subloops.ll new file mode 100644 index 000000000000..adbf47defe8f --- /dev/null +++ b/test/Transforms/LoopUnroll/update-loop-info-in-subloops.ll @@ -0,0 +1,35 @@ +; RUN: opt -S < %s -loop-unroll -block-freq | FileCheck %s +; Crasher from PR20987. + +; CHECK: define void @update_loop_info_in_subloops +; CHECK: entry: +; CHECK: L: +; CHECK: L.inner: +; CHECK: L.inner.latch: +; CHECK: L.latch: +; CHECK: L.inner.1: +; CHECK: L.inner.latch.1: +; CHECK: L.latch.1: + +define void @update_loop_info_in_subloops() { +entry: + br label %L + +L: + %0 = phi i64 [ 1, %entry ], [ %1, %L.latch ] + br label %L.inner + +L.inner: + br label %L.inner.latch + +L.inner.latch: + br i1 false, label %L.latch, label %L.inner + +L.latch: + %1 = add i64 %0, 1 + %2 = icmp eq i64 %1, 3 + br i1 %2, label %exit, label %L + +exit: + ret void +} diff --git a/test/Transforms/LoopVectorize/12-12-11-if-conv.ll b/test/Transforms/LoopVectorize/12-12-11-if-conv.ll index 1e1396f80085..a292afbd5882 100644 --- a/test/Transforms/LoopVectorize/12-12-11-if-conv.ll +++ b/test/Transforms/LoopVectorize/12-12-11-if-conv.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -enable-if-conversion -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -enable-if-conversion -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/2012-10-20-infloop.ll b/test/Transforms/LoopVectorize/2012-10-20-infloop.ll index aa7cc0ee325d..b3eae690423d 100644 --- a/test/Transforms/LoopVectorize/2012-10-20-infloop.ll +++ b/test/Transforms/LoopVectorize/2012-10-20-infloop.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce ; Check that we don't fall into an infinite loop. define void @test() nounwind { diff --git a/test/Transforms/LoopVectorize/2012-10-22-isconsec.ll b/test/Transforms/LoopVectorize/2012-10-22-isconsec.ll index ae9f998fee26..16d64eab25c3 100644 --- a/test/Transforms/LoopVectorize/2012-10-22-isconsec.ll +++ b/test/Transforms/LoopVectorize/2012-10-22-isconsec.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -dce -force-vector-unroll=1 -force-vector-width=4 +; RUN: opt < %s -loop-vectorize -dce -force-vector-interleave=1 -force-vector-width=4 ; Check that we don't crash. diff --git a/test/Transforms/LoopVectorize/AArch64/sdiv-pow2.ll b/test/Transforms/LoopVectorize/AArch64/sdiv-pow2.ll new file mode 100644 index 000000000000..a01d54312a60 --- /dev/null +++ b/test/Transforms/LoopVectorize/AArch64/sdiv-pow2.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -loop-vectorize -mtriple=aarch64-unknown-linux-gnu -mcpu=cortex-a57 -S | FileCheck %s +target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-gnu" + +%struct.anon = type { [100 x i32], i32, [100 x i32] } + +@Foo = common global %struct.anon zeroinitializer, align 4 + +; CHECK-LABEL: @foo( +; CHECK: load <4 x i32>* +; CHECK: sdiv <4 x i32> +; CHECK: store <4 x i32> + +define void @foo(){ +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %arrayidx = getelementptr inbounds %struct.anon* @Foo, i64 0, i32 2, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %div = sdiv i32 %0, 2 + %arrayidx2 = getelementptr inbounds %struct.anon* @Foo, i64 0, i32 0, i64 %indvars.iv + store i32 %div, i32* %arrayidx2, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond = icmp eq i64 %indvars.iv.next, 100 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} diff --git a/test/Transforms/LoopVectorize/X86/already-vectorized.ll b/test/Transforms/LoopVectorize/X86/already-vectorized.ll index 9c69ba87f392..29d74a0645e8 100644 --- a/test/Transforms/LoopVectorize/X86/already-vectorized.ll +++ b/test/Transforms/LoopVectorize/X86/already-vectorized.ll @@ -39,8 +39,8 @@ for.end: ; preds = %for.body } ; Now, we check for the Hint metadata -; CHECK: [[vect]] = metadata !{metadata [[vect]], metadata [[width:![0-9]+]], metadata [[unroll:![0-9]+]]} -; CHECK: [[width]] = metadata !{metadata !"llvm.loop.vectorize.width", i32 1} -; CHECK: [[unroll]] = metadata !{metadata !"llvm.loop.interleave.count", i32 1} -; CHECK: [[scalar]] = metadata !{metadata [[scalar]], metadata [[width]], metadata [[unroll]]} +; CHECK: [[vect]] = distinct !{[[vect]], [[width:![0-9]+]], [[unroll:![0-9]+]]} +; CHECK: [[width]] = !{!"llvm.loop.vectorize.width", i32 1} +; CHECK: [[unroll]] = !{!"llvm.loop.interleave.count", i32 1} +; CHECK: [[scalar]] = distinct !{[[scalar]], [[width]], [[unroll]]} diff --git a/test/Transforms/LoopVectorize/X86/assume.ll b/test/Transforms/LoopVectorize/X86/assume.ll new file mode 100644 index 000000000000..a94e24dd7e9c --- /dev/null +++ b/test/Transforms/LoopVectorize/X86/assume.ll @@ -0,0 +1,100 @@ +; RUN: opt < %s -loop-vectorize -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7 -S | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: nounwind uwtable +define void @test1(float* noalias nocapture %a, float* noalias nocapture readonly %b) #0 { +entry: + br label %for.body + +; CHECK-LABEL: @test1 +; CHECK: vector.body: +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: for.body: +; CHECK: ret void + +for.body: ; preds = %for.body, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %arrayidx = getelementptr inbounds float* %b, i64 %indvars.iv + %0 = load float* %arrayidx, align 4 + %cmp1 = fcmp ogt float %0, 1.000000e+02 + tail call void @llvm.assume(i1 %cmp1) + %add = fadd float %0, 1.000000e+00 + %arrayidx5 = getelementptr inbounds float* %a, i64 %indvars.iv + store float %add, float* %arrayidx5, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond = icmp eq i64 %indvars.iv, 1599 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} + +; Function Attrs: nounwind +declare void @llvm.assume(i1) #1 + +attributes #0 = { nounwind uwtable } +attributes #1 = { nounwind } + +%struct.data = type { float*, float* } + +; Function Attrs: nounwind uwtable +define void @test2(%struct.data* nocapture readonly %d) #0 { +entry: + %b = getelementptr inbounds %struct.data* %d, i64 0, i32 1 + %0 = load float** %b, align 8 + %ptrint = ptrtoint float* %0 to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + %a = getelementptr inbounds %struct.data* %d, i64 0, i32 0 + %1 = load float** %a, align 8 + %ptrint2 = ptrtoint float* %1 to i64 + %maskedptr3 = and i64 %ptrint2, 31 + %maskcond4 = icmp eq i64 %maskedptr3, 0 + br label %for.body + +; CHECK-LABEL: @test2 +; CHECK: vector.body: +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: @llvm.assume +; CHECK: for.body: +; CHECK: ret void + +for.body: ; preds = %for.body, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + tail call void @llvm.assume(i1 %maskcond) + %arrayidx = getelementptr inbounds float* %0, i64 %indvars.iv + %2 = load float* %arrayidx, align 4 + %add = fadd float %2, 1.000000e+00 + tail call void @llvm.assume(i1 %maskcond4) + %arrayidx5 = getelementptr inbounds float* %1, i64 %indvars.iv + store float %add, float* %arrayidx5, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond = icmp eq i64 %indvars.iv, 1599 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} + diff --git a/test/Transforms/LoopVectorize/X86/gcc-examples.ll b/test/Transforms/LoopVectorize/X86/gcc-examples.ll index e1113fdd911c..05403cd5b61b 100644 --- a/test/Transforms/LoopVectorize/X86/gcc-examples.ll +++ b/test/Transforms/LoopVectorize/X86/gcc-examples.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -loop-vectorize -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7 -dce -instcombine -S | FileCheck %s -; RUN: opt < %s -loop-vectorize -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7 -force-vector-unroll=0 -dce -instcombine -S | FileCheck %s -check-prefix=UNROLL +; RUN: opt < %s -loop-vectorize -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7 -force-vector-interleave=0 -dce -instcombine -S | FileCheck %s -check-prefix=UNROLL 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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/X86/illegal-parallel-loop-uniform-write.ll b/test/Transforms/LoopVectorize/X86/illegal-parallel-loop-uniform-write.ll index d6120e76cc0b..46efaf0e8531 100644 --- a/test/Transforms/LoopVectorize/X86/illegal-parallel-loop-uniform-write.ll +++ b/test/Transforms/LoopVectorize/X86/illegal-parallel-loop-uniform-write.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-unknown-linux-gnu" @@ -50,7 +50,7 @@ for.end15: ; preds = %for.end.us, %entry attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } -!3 = metadata !{metadata !4, metadata !5} -!4 = metadata !{metadata !4} -!5 = metadata !{metadata !5} +!3 = !{!4, !5} +!4 = !{!4} +!5 = !{!5} diff --git a/test/Transforms/LoopVectorize/X86/masked_load_store.ll b/test/Transforms/LoopVectorize/X86/masked_load_store.ll new file mode 100644 index 000000000000..0708471e643a --- /dev/null +++ b/test/Transforms/LoopVectorize/X86/masked_load_store.ll @@ -0,0 +1,420 @@ +; RUN: opt < %s -O3 -mcpu=corei7-avx -S | FileCheck %s -check-prefix=AVX1 +; RUN: opt < %s -O3 -mcpu=core-avx2 -S | FileCheck %s -check-prefix=AVX2 +; RUN: opt < %s -O3 -mcpu=knl -S | FileCheck %s -check-prefix=AVX512 + +;AVX1-NOT: llvm.masked + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc_linux" + +; The source code: +; +;void foo1(int *A, int *B, int *trigger) { +; +; for (int i=0; i<10000; i++) { +; if (trigger[i] < 100) { +; A[i] = B[i] + trigger[i]; +; } +; } +;} + +;AVX2-LABEL: @foo1 +;AVX2: icmp slt <8 x i32> %wide.load, <i32 100, i32 100, i32 100 +;AVX2: call <8 x i32> @llvm.masked.load.v8i32 +;AVX2: add nsw <8 x i32> +;AVX2: call void @llvm.masked.store.v8i32 +;AVX2: ret void + +;AVX512-LABEL: @foo1 +;AVX512: icmp slt <16 x i32> %wide.load, <i32 100, i32 100, i32 100 +;AVX512: call <16 x i32> @llvm.masked.load.v16i32 +;AVX512: add nsw <16 x i32> +;AVX512: call void @llvm.masked.store.v16i32 +;AVX512: ret void + +; Function Attrs: nounwind uwtable +define void @foo1(i32* %A, i32* %B, i32* %trigger) { +entry: + %A.addr = alloca i32*, align 8 + %B.addr = alloca i32*, align 8 + %trigger.addr = alloca i32*, align 8 + %i = alloca i32, align 4 + store i32* %A, i32** %A.addr, align 8 + store i32* %B, i32** %B.addr, align 8 + store i32* %trigger, i32** %trigger.addr, align 8 + store i32 0, i32* %i, align 4 + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %0 = load i32* %i, align 4 + %cmp = icmp slt i32 %0, 10000 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %1 = load i32* %i, align 4 + %idxprom = sext i32 %1 to i64 + %2 = load i32** %trigger.addr, align 8 + %arrayidx = getelementptr inbounds i32* %2, i64 %idxprom + %3 = load i32* %arrayidx, align 4 + %cmp1 = icmp slt i32 %3, 100 + br i1 %cmp1, label %if.then, label %if.end + +if.then: ; preds = %for.body + %4 = load i32* %i, align 4 + %idxprom2 = sext i32 %4 to i64 + %5 = load i32** %B.addr, align 8 + %arrayidx3 = getelementptr inbounds i32* %5, i64 %idxprom2 + %6 = load i32* %arrayidx3, align 4 + %7 = load i32* %i, align 4 + %idxprom4 = sext i32 %7 to i64 + %8 = load i32** %trigger.addr, align 8 + %arrayidx5 = getelementptr inbounds i32* %8, i64 %idxprom4 + %9 = load i32* %arrayidx5, align 4 + %add = add nsw i32 %6, %9 + %10 = load i32* %i, align 4 + %idxprom6 = sext i32 %10 to i64 + %11 = load i32** %A.addr, align 8 + %arrayidx7 = getelementptr inbounds i32* %11, i64 %idxprom6 + store i32 %add, i32* %arrayidx7, align 4 + br label %if.end + +if.end: ; preds = %if.then, %for.body + br label %for.inc + +for.inc: ; preds = %if.end + %12 = load i32* %i, align 4 + %inc = add nsw i32 %12, 1 + store i32 %inc, i32* %i, align 4 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +; The source code: +; +;void foo2(float *A, float *B, int *trigger) { +; +; for (int i=0; i<10000; i++) { +; if (trigger[i] < 100) { +; A[i] = B[i] + trigger[i]; +; } +; } +;} + +;AVX2-LABEL: @foo2 +;AVX2: icmp slt <8 x i32> %wide.load, <i32 100, i32 100, i32 100 +;AVX2: call <8 x float> @llvm.masked.load.v8f32 +;AVX2: fadd <8 x float> +;AVX2: call void @llvm.masked.store.v8f32 +;AVX2: ret void + +;AVX512-LABEL: @foo2 +;AVX512: icmp slt <16 x i32> %wide.load, <i32 100, i32 100, i32 100 +;AVX512: call <16 x float> @llvm.masked.load.v16f32 +;AVX512: fadd <16 x float> +;AVX512: call void @llvm.masked.store.v16f32 +;AVX512: ret void + +; Function Attrs: nounwind uwtable +define void @foo2(float* %A, float* %B, i32* %trigger) { +entry: + %A.addr = alloca float*, align 8 + %B.addr = alloca float*, align 8 + %trigger.addr = alloca i32*, align 8 + %i = alloca i32, align 4 + store float* %A, float** %A.addr, align 8 + store float* %B, float** %B.addr, align 8 + store i32* %trigger, i32** %trigger.addr, align 8 + store i32 0, i32* %i, align 4 + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %0 = load i32* %i, align 4 + %cmp = icmp slt i32 %0, 10000 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %1 = load i32* %i, align 4 + %idxprom = sext i32 %1 to i64 + %2 = load i32** %trigger.addr, align 8 + %arrayidx = getelementptr inbounds i32* %2, i64 %idxprom + %3 = load i32* %arrayidx, align 4 + %cmp1 = icmp slt i32 %3, 100 + br i1 %cmp1, label %if.then, label %if.end + +if.then: ; preds = %for.body + %4 = load i32* %i, align 4 + %idxprom2 = sext i32 %4 to i64 + %5 = load float** %B.addr, align 8 + %arrayidx3 = getelementptr inbounds float* %5, i64 %idxprom2 + %6 = load float* %arrayidx3, align 4 + %7 = load i32* %i, align 4 + %idxprom4 = sext i32 %7 to i64 + %8 = load i32** %trigger.addr, align 8 + %arrayidx5 = getelementptr inbounds i32* %8, i64 %idxprom4 + %9 = load i32* %arrayidx5, align 4 + %conv = sitofp i32 %9 to float + %add = fadd float %6, %conv + %10 = load i32* %i, align 4 + %idxprom6 = sext i32 %10 to i64 + %11 = load float** %A.addr, align 8 + %arrayidx7 = getelementptr inbounds float* %11, i64 %idxprom6 + store float %add, float* %arrayidx7, align 4 + br label %if.end + +if.end: ; preds = %if.then, %for.body + br label %for.inc + +for.inc: ; preds = %if.end + %12 = load i32* %i, align 4 + %inc = add nsw i32 %12, 1 + store i32 %inc, i32* %i, align 4 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +; The source code: +; +;void foo3(double *A, double *B, int *trigger) { +; +; for (int i=0; i<10000; i++) { +; if (trigger[i] < 100) { +; A[i] = B[i] + trigger[i]; +; } +; } +;} + +;AVX2-LABEL: @foo3 +;AVX2: icmp slt <4 x i32> %wide.load, <i32 100, i32 100, +;AVX2: call <4 x double> @llvm.masked.load.v4f64 +;AVX2: sitofp <4 x i32> %wide.load to <4 x double> +;AVX2: fadd <4 x double> +;AVX2: call void @llvm.masked.store.v4f64 +;AVX2: ret void + +;AVX512-LABEL: @foo3 +;AVX512: icmp slt <8 x i32> %wide.load, <i32 100, i32 100, +;AVX512: call <8 x double> @llvm.masked.load.v8f64 +;AVX512: sitofp <8 x i32> %wide.load to <8 x double> +;AVX512: fadd <8 x double> +;AVX512: call void @llvm.masked.store.v8f64 +;AVX512: ret void + + +; Function Attrs: nounwind uwtable +define void @foo3(double* %A, double* %B, i32* %trigger) #0 { +entry: + %A.addr = alloca double*, align 8 + %B.addr = alloca double*, align 8 + %trigger.addr = alloca i32*, align 8 + %i = alloca i32, align 4 + store double* %A, double** %A.addr, align 8 + store double* %B, double** %B.addr, align 8 + store i32* %trigger, i32** %trigger.addr, align 8 + store i32 0, i32* %i, align 4 + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %0 = load i32* %i, align 4 + %cmp = icmp slt i32 %0, 10000 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %1 = load i32* %i, align 4 + %idxprom = sext i32 %1 to i64 + %2 = load i32** %trigger.addr, align 8 + %arrayidx = getelementptr inbounds i32* %2, i64 %idxprom + %3 = load i32* %arrayidx, align 4 + %cmp1 = icmp slt i32 %3, 100 + br i1 %cmp1, label %if.then, label %if.end + +if.then: ; preds = %for.body + %4 = load i32* %i, align 4 + %idxprom2 = sext i32 %4 to i64 + %5 = load double** %B.addr, align 8 + %arrayidx3 = getelementptr inbounds double* %5, i64 %idxprom2 + %6 = load double* %arrayidx3, align 8 + %7 = load i32* %i, align 4 + %idxprom4 = sext i32 %7 to i64 + %8 = load i32** %trigger.addr, align 8 + %arrayidx5 = getelementptr inbounds i32* %8, i64 %idxprom4 + %9 = load i32* %arrayidx5, align 4 + %conv = sitofp i32 %9 to double + %add = fadd double %6, %conv + %10 = load i32* %i, align 4 + %idxprom6 = sext i32 %10 to i64 + %11 = load double** %A.addr, align 8 + %arrayidx7 = getelementptr inbounds double* %11, i64 %idxprom6 + store double %add, double* %arrayidx7, align 8 + br label %if.end + +if.end: ; preds = %if.then, %for.body + br label %for.inc + +for.inc: ; preds = %if.end + %12 = load i32* %i, align 4 + %inc = add nsw i32 %12, 1 + store i32 %inc, i32* %i, align 4 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +; The source code: +; +;void foo4(double *A, double *B, int *trigger) { +; +; for (int i=0; i<10000; i++) { +; if (trigger[i] < 100) { +; A[i] = B[i*2] + trigger[i]; << non-cosecutive access +; } +; } +;} + +;AVX2-LABEL: @foo4 +;AVX2-NOT: llvm.masked +;AVX2: ret void + +;AVX512-LABEL: @foo4 +;AVX512-NOT: llvm.masked +;AVX512: ret void + +; Function Attrs: nounwind uwtable +define void @foo4(double* %A, double* %B, i32* %trigger) { +entry: + %A.addr = alloca double*, align 8 + %B.addr = alloca double*, align 8 + %trigger.addr = alloca i32*, align 8 + %i = alloca i32, align 4 + store double* %A, double** %A.addr, align 8 + store double* %B, double** %B.addr, align 8 + store i32* %trigger, i32** %trigger.addr, align 8 + store i32 0, i32* %i, align 4 + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %0 = load i32* %i, align 4 + %cmp = icmp slt i32 %0, 10000 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %1 = load i32* %i, align 4 + %idxprom = sext i32 %1 to i64 + %2 = load i32** %trigger.addr, align 8 + %arrayidx = getelementptr inbounds i32* %2, i64 %idxprom + %3 = load i32* %arrayidx, align 4 + %cmp1 = icmp slt i32 %3, 100 + br i1 %cmp1, label %if.then, label %if.end + +if.then: ; preds = %for.body + %4 = load i32* %i, align 4 + %mul = mul nsw i32 %4, 2 + %idxprom2 = sext i32 %mul to i64 + %5 = load double** %B.addr, align 8 + %arrayidx3 = getelementptr inbounds double* %5, i64 %idxprom2 + %6 = load double* %arrayidx3, align 8 + %7 = load i32* %i, align 4 + %idxprom4 = sext i32 %7 to i64 + %8 = load i32** %trigger.addr, align 8 + %arrayidx5 = getelementptr inbounds i32* %8, i64 %idxprom4 + %9 = load i32* %arrayidx5, align 4 + %conv = sitofp i32 %9 to double + %add = fadd double %6, %conv + %10 = load i32* %i, align 4 + %idxprom6 = sext i32 %10 to i64 + %11 = load double** %A.addr, align 8 + %arrayidx7 = getelementptr inbounds double* %11, i64 %idxprom6 + store double %add, double* %arrayidx7, align 8 + br label %if.end + +if.end: ; preds = %if.then, %for.body + br label %for.inc + +for.inc: ; preds = %if.end + %12 = load i32* %i, align 4 + %inc = add nsw i32 %12, 1 + store i32 %inc, i32* %i, align 4 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +@a = common global [1 x i32*] zeroinitializer, align 8 +@c = common global i32* null, align 8 + +; The loop here should not be vectorized due to trapping +; constant expression +;AVX2-LABEL: @foo5 +;AVX2-NOT: llvm.masked +;AVX2: store i32 sdiv +;AVX2: ret void + +;AVX512-LABEL: @foo5 +;AVX512-NOT: llvm.masked +;AVX512: store i32 sdiv +;AVX512: ret void + +; Function Attrs: nounwind uwtable +define void @foo5(i32* %A, i32* %B, i32* %trigger) { +entry: + %A.addr = alloca i32*, align 8 + %B.addr = alloca i32*, align 8 + %trigger.addr = alloca i32*, align 8 + %i = alloca i32, align 4 + store i32* %A, i32** %A.addr, align 8 + store i32* %B, i32** %B.addr, align 8 + store i32* %trigger, i32** %trigger.addr, align 8 + store i32 0, i32* %i, align 4 + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %0 = load i32* %i, align 4 + %cmp = icmp slt i32 %0, 10000 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %1 = load i32* %i, align 4 + %idxprom = sext i32 %1 to i64 + %2 = load i32** %trigger.addr, align 8 + %arrayidx = getelementptr inbounds i32* %2, i64 %idxprom + %3 = load i32* %arrayidx, align 4 + %cmp1 = icmp slt i32 %3, 100 + br i1 %cmp1, label %if.then, label %if.end + +if.then: ; preds = %for.body + %4 = load i32* %i, align 4 + %idxprom2 = sext i32 %4 to i64 + %5 = load i32** %B.addr, align 8 + %arrayidx3 = getelementptr inbounds i32* %5, i64 %idxprom2 + %6 = load i32* %arrayidx3, align 4 + %7 = load i32* %i, align 4 + %idxprom4 = sext i32 %7 to i64 + %8 = load i32** %trigger.addr, align 8 + %arrayidx5 = getelementptr inbounds i32* %8, i64 %idxprom4 + %9 = load i32* %arrayidx5, align 4 + %add = add nsw i32 %6, %9 + %10 = load i32* %i, align 4 + %idxprom6 = sext i32 %10 to i64 + %11 = load i32** %A.addr, align 8 + %arrayidx7 = getelementptr inbounds i32* %11, i64 %idxprom6 + store i32 sdiv (i32 1, i32 zext (i1 icmp eq (i32** getelementptr inbounds ([1 x i32*]* @a, i64 0, i64 1), i32** @c) to i32)), i32* %arrayidx7, align 4 + br label %if.end + +if.end: ; preds = %if.then, %for.body + br label %for.inc + +for.inc: ; preds = %if.end + %12 = load i32* %i, align 4 + %inc = add nsw i32 %12, 1 + store i32 %inc, i32* %i, align 4 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + diff --git a/test/Transforms/LoopVectorize/X86/metadata-enable.ll b/test/Transforms/LoopVectorize/X86/metadata-enable.ll index 8e0ca417b404..7feb66ce6a98 100644 --- a/test/Transforms/LoopVectorize/X86/metadata-enable.ll +++ b/test/Transforms/LoopVectorize/X86/metadata-enable.ll @@ -170,7 +170,7 @@ for.end: ; preds = %for.body ret i32 %1 } -!0 = metadata !{metadata !0, metadata !1} -!1 = metadata !{metadata !"llvm.loop.vectorize.enable", i1 1} -!2 = metadata !{metadata !2, metadata !3} -!3 = metadata !{metadata !"llvm.loop.vectorize.enable", i1 0} +!0 = !{!0, !1} +!1 = !{!"llvm.loop.vectorize.enable", i1 1} +!2 = !{!2, !3} +!3 = !{!"llvm.loop.vectorize.enable", i1 0} diff --git a/test/Transforms/LoopVectorize/X86/min-trip-count-switch.ll b/test/Transforms/LoopVectorize/X86/min-trip-count-switch.ll index 8716cff77789..fd69dc46070e 100644 --- a/test/Transforms/LoopVectorize/X86/min-trip-count-switch.ll +++ b/test/Transforms/LoopVectorize/X86/min-trip-count-switch.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -vectorizer-min-trip-count=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -vectorizer-min-trip-count=1 -force-vector-width=4 -dce -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" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Transforms/LoopVectorize/X86/parallel-loops-after-reg2mem.ll b/test/Transforms/LoopVectorize/X86/parallel-loops-after-reg2mem.ll index 2c47fcb4d389..ad010443a5e0 100644 --- a/test/Transforms/LoopVectorize/X86/parallel-loops-after-reg2mem.ll +++ b/test/Transforms/LoopVectorize/X86/parallel-loops-after-reg2mem.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-unknown-linux-gnu" @@ -46,4 +46,4 @@ for.end: ; preds = %for.body ret void } -!3 = metadata !{metadata !3} +!3 = !{!3} diff --git a/test/Transforms/LoopVectorize/X86/parallel-loops.ll b/test/Transforms/LoopVectorize/X86/parallel-loops.ll index 7e156a9edad4..22ab52157498 100644 --- a/test/Transforms/LoopVectorize/X86/parallel-loops.ll +++ b/test/Transforms/LoopVectorize/X86/parallel-loops.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-unknown-linux-gnu" @@ -104,8 +104,8 @@ for.end: ; preds = %for.body ret void } -!3 = metadata !{metadata !3} -!4 = metadata !{metadata !4} -!5 = metadata !{metadata !3, metadata !4} -!6 = metadata !{metadata !6} -!7 = metadata !{metadata !7} +!3 = !{!3} +!4 = !{!4} +!5 = !{!3, !4} +!6 = !{!6} +!7 = !{!7} diff --git a/test/Transforms/LoopVectorize/X86/powof2div.ll b/test/Transforms/LoopVectorize/X86/powof2div.ll new file mode 100644 index 000000000000..054da8ed20ae --- /dev/null +++ b/test/Transforms/LoopVectorize/X86/powof2div.ll @@ -0,0 +1,32 @@ +; RUN: opt < %s -loop-vectorize -mtriple=x86_64-unknown-linux-gnu -S | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.anon = type { [100 x i32], i32, [100 x i32] } + +@Foo = common global %struct.anon zeroinitializer, align 4 + +;CHECK-LABEL: @foo( +;CHECK: load <4 x i32>* +;CHECK: sdiv <4 x i32> +;CHECK: store <4 x i32> + +define void @foo(){ +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %arrayidx = getelementptr inbounds %struct.anon* @Foo, i64 0, i32 2, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %div = sdiv i32 %0, 2 + %arrayidx2 = getelementptr inbounds %struct.anon* @Foo, i64 0, i32 0, i64 %indvars.iv + store i32 %div, i32* %arrayidx2, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond = icmp eq i64 %indvars.iv.next, 100 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} + diff --git a/test/Transforms/LoopVectorize/X86/small-size.ll b/test/Transforms/LoopVectorize/X86/small-size.ll index bcf16aa5db13..8c7a881be46f 100644 --- a/test/Transforms/LoopVectorize/X86/small-size.ll +++ b/test/Transforms/LoopVectorize/X86/small-size.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basicaa -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -loop-vectorize-with-block-frequency -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -basicaa -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -loop-vectorize-with-block-frequency -dce -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" target triple = "x86_64-apple-macosx10.8.0" @@ -139,7 +139,7 @@ define void @example4(i32 %n, i32* noalias nocapture %p, i32* noalias nocapture ret void } -!0 = metadata !{metadata !"branch_weights", i32 64, i32 4} +!0 = !{!"branch_weights", i32 64, i32 4} ; We can't vectorize this one because we need a runtime ptr check. ;CHECK-LABEL: @example23( diff --git a/test/Transforms/LoopVectorize/X86/tripcount.ll b/test/Transforms/LoopVectorize/X86/tripcount.ll index 6b38bacf8888..a4ec6948a2f0 100644 --- a/test/Transforms/LoopVectorize/X86/tripcount.ll +++ b/test/Transforms/LoopVectorize/X86/tripcount.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -loop-vectorize -force-vector-width=2 -force-vector-unroll=1 -mcpu=prescott < %s | FileCheck %s +; RUN: opt -S -loop-vectorize -force-vector-width=2 -force-vector-interleave=1 -mcpu=prescott < %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:32:32-n8:16:32-S128" target triple = "i386-unknown-freebsd11.0" diff --git a/test/Transforms/LoopVectorize/X86/unroll-small-loops.ll b/test/Transforms/LoopVectorize/X86/unroll-small-loops.ll index d5024bb13210..716dc08a55ac 100644 --- a/test/Transforms/LoopVectorize/X86/unroll-small-loops.ll +++ b/test/Transforms/LoopVectorize/X86/unroll-small-loops.ll @@ -1,6 +1,6 @@ -; RUN: opt < %s -loop-vectorize -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx -force-vector-width=4 -force-vector-unroll=0 -dce -S \ +; RUN: opt < %s -loop-vectorize -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx -force-vector-width=4 -force-vector-interleave=0 -dce -S \ ; RUN: | FileCheck %s --check-prefix=CHECK-VECTOR -; RUN: opt < %s -loop-vectorize -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx -force-vector-width=1 -force-vector-unroll=0 -dce -S \ +; RUN: opt < %s -loop-vectorize -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx -force-vector-width=1 -force-vector-interleave=0 -dce -S \ ; RUN: | FileCheck %s --check-prefix=CHECK-SCALAR 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" diff --git a/test/Transforms/LoopVectorize/X86/unroll_selection.ll b/test/Transforms/LoopVectorize/X86/unroll_selection.ll index 2d7b663804f5..c684b4e79b14 100644 --- a/test/Transforms/LoopVectorize/X86/unroll_selection.ll +++ b/test/Transforms/LoopVectorize/X86/unroll_selection.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx -force-vector-width=4 -force-vector-unroll=0 -dce -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx -force-vector-width=4 -force-vector-interleave=0 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/X86/vect.omp.force.ll b/test/Transforms/LoopVectorize/X86/vect.omp.force.ll index 074313bde6f5..a781fbedb404 100644 --- a/test/Transforms/LoopVectorize/X86/vect.omp.force.ll +++ b/test/Transforms/LoopVectorize/X86/vect.omp.force.ll @@ -52,8 +52,8 @@ for.end: ret void } -!1 = metadata !{metadata !1, metadata !2} -!2 = metadata !{metadata !"llvm.loop.vectorize.enable", i1 true} +!1 = !{!1, !2} +!2 = !{!"llvm.loop.vectorize.enable", i1 true} ; ; This method will not be vectorized, as scalar cost is lower than any of vector costs. @@ -89,5 +89,5 @@ for.end: declare float @llvm.sin.f32(float) nounwind readnone ; Dummy metadata -!3 = metadata !{metadata !3} +!3 = !{!3} diff --git a/test/Transforms/LoopVectorize/X86/vect.omp.force.small-tc.ll b/test/Transforms/LoopVectorize/X86/vect.omp.force.small-tc.ll index 97c31a148e3a..e39e6b57dd96 100644 --- a/test/Transforms/LoopVectorize/X86/vect.omp.force.small-tc.ll +++ b/test/Transforms/LoopVectorize/X86/vect.omp.force.small-tc.ll @@ -43,8 +43,8 @@ for.end: ret void } -!1 = metadata !{metadata !1, metadata !2} -!2 = metadata !{metadata !"llvm.loop.vectorize.enable", i1 true} +!1 = !{!1, !2} +!2 = !{!"llvm.loop.vectorize.enable", i1 true} ; ; This loop will not be vectorized as the trip count is below the threshold. @@ -69,5 +69,5 @@ for.end: ret void } -!3 = metadata !{metadata !3} +!3 = !{!3} diff --git a/test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll b/test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll index 93f24cbf4909..011ce8eac556 100644 --- a/test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll +++ b/test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll @@ -24,10 +24,10 @@ ; File, line, and column should match those specified in the metadata ; CHECK: remark: source.cpp:4:5: loop not vectorized: could not determine number of loop iterations -; CHECK: remark: source.cpp:4:5: loop not vectorized: vectorization was not specified +; CHECK: remark: source.cpp:4:5: loop not vectorized: use -Rpass-analysis=loop-vectorize for more info ; CHECK: remark: source.cpp:13:5: loop not vectorized: vector width and interleave count are explicitly set to 1 ; CHECK: remark: source.cpp:19:5: loop not vectorized: cannot identify array bounds -; CHECK: remark: source.cpp:19:5: loop not vectorized: vectorization is explicitly enabled +; CHECK: remark: source.cpp:19:5: loop not vectorized: use -Rpass-analysis=loop-vectorize for more info ; CHECK: warning: source.cpp:19:5: loop not vectorized: failed explicitly specified loop vectorization ; CHECK: _Z4testPii @@ -122,40 +122,40 @@ attributes #0 = { nounwind } !llvm.module.flags = !{!9, !10} !llvm.ident = !{!11} -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.5.0", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 2} -!1 = metadata !{metadata !"source.cpp", metadata !"."} -!2 = metadata !{} -!3 = metadata !{metadata !4, metadata !7, metadata !8} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"test", metadata !"test", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (i32*, i32)* @_Z4testPii, null, null, metadata !2, i32 1} -!5 = metadata !{i32 786473, metadata !1} -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} -!7 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"test_disabled", metadata !"test_disabled", metadata !"", i32 10, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (i32*, i32)* @_Z13test_disabledPii, null, null, metadata !2, i32 10} -!8 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"test_array_bounds", metadata !"test_array_bounds", metadata !"", i32 16, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (i32*, i32*, i32)* @_Z17test_array_boundsPiS_i, null, null, metadata !2, i32 16} -!9 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} -!10 = metadata !{i32 2, metadata !"Debug Info Version", i32 1} -!11 = metadata !{metadata !"clang version 3.5.0"} -!12 = metadata !{i32 3, i32 8, metadata !13, null} -!13 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 3, i32 0, i32 0} -!14 = metadata !{metadata !14, metadata !15, metadata !15} -!15 = metadata !{metadata !"llvm.loop.vectorize.enable", i1 true} -!16 = metadata !{i32 4, i32 5, metadata !17, null} -!17 = metadata !{i32 786443, metadata !1, metadata !13, i32 3, i32 36, i32 0, i32 1} -!18 = metadata !{metadata !19, metadata !19, i64 0} -!19 = metadata !{metadata !"int", metadata !20, i64 0} -!20 = metadata !{metadata !"omnipotent char", metadata !21, i64 0} -!21 = metadata !{metadata !"Simple C/C++ TBAA"} -!22 = metadata !{i32 5, i32 9, metadata !23, null} -!23 = metadata !{i32 786443, metadata !1, metadata !17, i32 5, i32 9, i32 0, i32 2} -!24 = metadata !{i32 8, i32 1, metadata !4, null} -!25 = metadata !{i32 12, i32 8, metadata !26, null} -!26 = metadata !{i32 786443, metadata !1, metadata !7, i32 12, i32 3, i32 0, i32 3} -!27 = metadata !{metadata !27, metadata !28, metadata !29} -!28 = metadata !{metadata !"llvm.loop.interleave.count", i32 1} -!29 = metadata !{metadata !"llvm.loop.vectorize.width", i32 1} -!30 = metadata !{i32 13, i32 5, metadata !26, null} -!31 = metadata !{i32 14, i32 1, metadata !7, null} -!32 = metadata !{i32 18, i32 8, metadata !33, null} -!33 = metadata !{i32 786443, metadata !1, metadata !8, i32 18, i32 3, i32 0, i32 4} -!34 = metadata !{metadata !34, metadata !15} -!35 = metadata !{i32 19, i32 5, metadata !33, null} -!36 = metadata !{i32 20, i32 1, metadata !8, null} +!0 = !{!"0x11\004\00clang version 3.5.0\001\00\006\00\002", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [./source.cpp] [DW_LANG_C_plus_plus] +!1 = !{!"source.cpp", !"."} +!2 = !{} +!3 = !{!4, !7, !8} +!4 = !{!"0x2e\00test\00test\00\001\000\001\000\006\00256\001\001", !1, !5, !6, null, void (i32*, i32)* @_Z4testPii, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [test] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [./source.cpp] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{!"0x2e\00test_disabled\00test_disabled\00\0010\000\001\000\006\00256\001\0010", !1, !5, !6, null, void (i32*, i32)* @_Z13test_disabledPii, null, null, !2} ; [ DW_TAG_subprogram ] [line 10] [def] [test_disabled] +!8 = !{!"0x2e\00test_array_bounds\00test_array_bounds\00\0016\000\001\000\006\00256\001\0016", !1, !5, !6, null, void (i32*, i32*, i32)* @_Z17test_array_boundsPiS_i, null, null, !2} ; [ DW_TAG_subprogram ] [line 16] [def] [test_array_bounds] +!9 = !{i32 2, !"Dwarf Version", i32 2} +!10 = !{i32 2, !"Debug Info Version", i32 2} +!11 = !{!"clang version 3.5.0"} +!12 = !MDLocation(line: 3, column: 8, scope: !13) +!13 = !{!"0xb\003\003\000", !1, !4} ; [ DW_TAG_lexical_block ] +!14 = !{!14, !15, !15} +!15 = !{!"llvm.loop.vectorize.enable", i1 true} +!16 = !MDLocation(line: 4, column: 5, scope: !17) +!17 = !{!"0xb\003\0036\000", !1, !13} ; [ DW_TAG_lexical_block ] +!18 = !{!19, !19, i64 0} +!19 = !{!"int", !20, i64 0} +!20 = !{!"omnipotent char", !21, i64 0} +!21 = !{!"Simple C/C++ TBAA"} +!22 = !MDLocation(line: 5, column: 9, scope: !23) +!23 = !{!"0xb\005\009\000", !1, !17} ; [ DW_TAG_lexical_block ] +!24 = !MDLocation(line: 8, column: 1, scope: !4) +!25 = !MDLocation(line: 12, column: 8, scope: !26) +!26 = !{!"0xb\0012\003\000", !1, !7} ; [ DW_TAG_lexical_block ] +!27 = !{!27, !28, !29} +!28 = !{!"llvm.loop.interleave.count", i32 1} +!29 = !{!"llvm.loop.vectorize.width", i32 1} +!30 = !MDLocation(line: 13, column: 5, scope: !26) +!31 = !MDLocation(line: 14, column: 1, scope: !7) +!32 = !MDLocation(line: 18, column: 8, scope: !33) +!33 = !{!"0xb\0018\003\000", !1, !8} ; [ DW_TAG_lexical_block ] +!34 = !{!34, !15} +!35 = !MDLocation(line: 19, column: 5, scope: !33) +!36 = !MDLocation(line: 20, column: 1, scope: !8) diff --git a/test/Transforms/LoopVectorize/X86/vectorization-remarks.ll b/test/Transforms/LoopVectorize/X86/vectorization-remarks.ll index f6834477ff51..16fe370464b0 100644 --- a/test/Transforms/LoopVectorize/X86/vectorization-remarks.ll +++ b/test/Transforms/LoopVectorize/X86/vectorization-remarks.ll @@ -1,6 +1,6 @@ ; RUN: opt < %s -loop-vectorize -mtriple=x86_64-unknown-linux -S -pass-remarks='loop-vectorize' 2>&1 | FileCheck -check-prefix=VECTORIZED %s -; RUN: opt < %s -loop-vectorize -force-vector-width=1 -force-vector-unroll=4 -mtriple=x86_64-unknown-linux -S -pass-remarks='loop-vectorize' 2>&1 | FileCheck -check-prefix=UNROLLED %s -; RUN: opt < %s -loop-vectorize -force-vector-width=1 -force-vector-unroll=1 -mtriple=x86_64-unknown-linux -S -pass-remarks-analysis='loop-vectorize' 2>&1 | FileCheck -check-prefix=NONE %s +; RUN: opt < %s -loop-vectorize -force-vector-width=1 -force-vector-interleave=4 -mtriple=x86_64-unknown-linux -S -pass-remarks='loop-vectorize' 2>&1 | FileCheck -check-prefix=UNROLLED %s +; RUN: opt < %s -loop-vectorize -force-vector-width=1 -force-vector-interleave=1 -mtriple=x86_64-unknown-linux -S -pass-remarks-analysis='loop-vectorize' 2>&1 | FileCheck -check-prefix=NONE %s ; This code has all the !dbg annotations needed to track source line information, ; but is missing the llvm.dbg.cu annotation. This prevents code generation from @@ -49,26 +49,26 @@ declare void @ibar(i32*) #1 !llvm.module.flags = !{!7, !8} !llvm.ident = !{!9} -!1 = metadata !{metadata !"vectorization-remarks.c", metadata !"."} -!2 = metadata !{} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 5, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i32 (i32)* @foo, null, null, metadata !2, i32 6} ; [ DW_TAG_subprogram ] [line 5] [def] [scope 6] [foo] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [./vectorization-remarks.c] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!8 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} -!9 = metadata !{metadata !"clang version 3.5.0 "} -!10 = metadata !{i32 8, i32 3, metadata !4, null} ; [ DW_TAG_imported_declaration ] -!11 = metadata !{metadata !12, metadata !12, i64 0} -!12 = metadata !{metadata !"int", metadata !13, i64 0} -!13 = metadata !{metadata !"omnipotent char", metadata !14, i64 0} -!14 = metadata !{metadata !"Simple C/C++ TBAA"} -!15 = metadata !{i32 17, i32 8, metadata !16, null} -!16 = metadata !{i32 786443, metadata !1, metadata !17, i32 17, i32 8, i32 2, i32 3} ; [ DW_TAG_lexical_block ] [./vectorization-remarks.c] -!17 = metadata !{i32 786443, metadata !1, metadata !18, i32 17, i32 8, i32 1, i32 2} ; [ DW_TAG_lexical_block ] [./vectorization-remarks.c] -!18 = metadata !{i32 786443, metadata !1, metadata !4, i32 17, i32 3, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [./vectorization-remarks.c] -!19 = metadata !{i32 18, i32 5, metadata !20, null} -!20 = metadata !{i32 786443, metadata !1, metadata !18, i32 17, i32 27, i32 0, i32 1} ; [ DW_TAG_lexical_block ] [./vectorization-remarks.c] -!21 = metadata !{metadata !13, metadata !13, i64 0} -!22 = metadata !{i32 20, i32 3, metadata !4, null} -!23 = metadata !{i32 21, i32 3, metadata !4, null} +!1 = !{!"vectorization-remarks.c", !"."} +!2 = !{} +!3 = !{!4} +!4 = !{!"0x2e\00foo\00foo\00\005\000\001\000\006\00256\001\006", !1, !5, !6, null, i32 (i32)* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 5] [def] [scope 6] [foo] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [./vectorization-remarks.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 1, !"Debug Info Version", i32 2} +!9 = !{!"clang version 3.5.0 "} +!10 = !MDLocation(line: 8, column: 3, scope: !4) +!11 = !{!12, !12, i64 0} +!12 = !{!"int", !13, i64 0} +!13 = !{!"omnipotent char", !14, i64 0} +!14 = !{!"Simple C/C++ TBAA"} +!15 = !MDLocation(line: 17, column: 8, scope: !16) +!16 = !{!"0xb\0017\008\002", !1, !17} ; [ DW_TAG_lexical_block ] [./vectorization-remarks.c] +!17 = !{!"0xb\0017\008\001", !1, !18} ; [ DW_TAG_lexical_block ] [./vectorization-remarks.c] +!18 = !{!"0xb\0017\003\000", !1, !4} ; [ DW_TAG_lexical_block ] [./vectorization-remarks.c] +!19 = !MDLocation(line: 18, column: 5, scope: !20) +!20 = !{!"0xb\0017\0027\000", !1, !18} ; [ DW_TAG_lexical_block ] [./vectorization-remarks.c] +!21 = !{!13, !13, i64 0} +!22 = !MDLocation(line: 20, column: 3, scope: !4) +!23 = !MDLocation(line: 21, column: 3, scope: !4) diff --git a/test/Transforms/LoopVectorize/X86/x86_fp80-vector-store.ll b/test/Transforms/LoopVectorize/X86/x86_fp80-vector-store.ll index efc93d94a7c5..d8e5403d2d4e 100644 --- a/test/Transforms/LoopVectorize/X86/x86_fp80-vector-store.ll +++ b/test/Transforms/LoopVectorize/X86/x86_fp80-vector-store.ll @@ -1,4 +1,4 @@ -; RUN: opt -O3 -loop-vectorize -force-vector-unroll=1 -force-vector-width=2 -S < %s | FileCheck %s +; RUN: opt -O3 -loop-vectorize -force-vector-interleave=1 -force-vector-width=2 -S < %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" target triple = "x86_64-apple-macosx10.7.0" diff --git a/test/Transforms/LoopVectorize/XCore/no-vector-registers.ll b/test/Transforms/LoopVectorize/XCore/no-vector-registers.ll index a099daa740e5..cab333d06406 100644 --- a/test/Transforms/LoopVectorize/XCore/no-vector-registers.ll +++ b/test/Transforms/LoopVectorize/XCore/no-vector-registers.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-width=4 -force-vector-unroll=2 -S -mtriple=xcore | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-width=4 -force-vector-interleave=2 -S -mtriple=xcore | FileCheck %s target datalayout = "e-p:32:32:32-a0:0:32-n32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f16:16:32-f32:32:32-f64:32:32" target triple = "xcore" diff --git a/test/Transforms/LoopVectorize/align.ll b/test/Transforms/LoopVectorize/align.ll index 84b03615d374..f2fb8b91b46e 100644 --- a/test/Transforms/LoopVectorize/align.ll +++ b/test/Transforms/LoopVectorize/align.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/bsd_regex.ll b/test/Transforms/LoopVectorize/bsd_regex.ll index 7b712729a1cd..7a3e79893da3 100644 --- a/test/Transforms/LoopVectorize/bsd_regex.ll +++ b/test/Transforms/LoopVectorize/bsd_regex.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -loop-vectorize -dce -instcombine -force-vector-width=2 -force-vector-unroll=2 < %s | FileCheck %s +; RUN: opt -S -loop-vectorize -dce -instcombine -force-vector-width=2 -force-vector-interleave=2 < %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" diff --git a/test/Transforms/LoopVectorize/bzip_reverse_loops.ll b/test/Transforms/LoopVectorize/bzip_reverse_loops.ll index 2648bbea8035..d7cbad06ddf0 100644 --- a/test/Transforms/LoopVectorize/bzip_reverse_loops.ll +++ b/test/Transforms/LoopVectorize/bzip_reverse_loops.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S -enable-if-conversion | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S -enable-if-conversion | 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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/calloc.ll b/test/Transforms/LoopVectorize/calloc.ll index 55c0a605450f..5f441f3e238f 100644 --- a/test/Transforms/LoopVectorize/calloc.ll +++ b/test/Transforms/LoopVectorize/calloc.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basicaa -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -basicaa -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.9.0" diff --git a/test/Transforms/LoopVectorize/cast-induction.ll b/test/Transforms/LoopVectorize/cast-induction.ll index 255ce9c77eaf..4f92d33ff528 100644 --- a/test/Transforms/LoopVectorize/cast-induction.ll +++ b/test/Transforms/LoopVectorize/cast-induction.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s ; rdar://problem/12848162 diff --git a/test/Transforms/LoopVectorize/conditional-assignment.ll b/test/Transforms/LoopVectorize/conditional-assignment.ll new file mode 100644 index 000000000000..38e9c4f9a61c --- /dev/null +++ b/test/Transforms/LoopVectorize/conditional-assignment.ll @@ -0,0 +1,58 @@ +; RUN: opt < %s -loop-vectorize -S -pass-remarks-missed='loop-vectorize' -pass-remarks-analysis='loop-vectorize' 2>&1 | FileCheck %s + +; CHECK: remark: source.c:2:8: loop not vectorized: store that is conditionally executed prevents vectorization + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.9.0" + +; Function Attrs: nounwind ssp uwtable +define void @conditional_store(i32* noalias nocapture %indices) #0 { +entry: + br label %for.body, !dbg !10 + +for.body: ; preds = %for.inc, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.inc ] + %arrayidx = getelementptr inbounds i32* %indices, i64 %indvars.iv, !dbg !12 + %0 = load i32* %arrayidx, align 4, !dbg !12, !tbaa !14 + %cmp1 = icmp eq i32 %0, 1024, !dbg !12 + br i1 %cmp1, label %if.then, label %for.inc, !dbg !12 + +if.then: ; preds = %for.body + store i32 0, i32* %arrayidx, align 4, !dbg !18, !tbaa !14 + br label %for.inc, !dbg !18 + +for.inc: ; preds = %for.body, %if.then + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !10 + %exitcond = icmp eq i64 %indvars.iv.next, 4096, !dbg !10 + br i1 %exitcond, label %for.end, label %for.body, !dbg !10 + +for.end: ; preds = %for.inc + ret void, !dbg !19 +} + +attributes #0 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!7, !8} +!llvm.ident = !{!9} + +!0 = !{!"0x11\0012\00clang version 3.6.0\001\00\000\00\002", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] +!1 = !{!"source.c", !"."} +!2 = !{} +!3 = !{!4} +!4 = !{!"0x2e\00conditional_store\00conditional_store\00\001\000\001\000\006\00256\001\001", !1, !5, !6, null, void (i32*)* @conditional_store, null, null, !2} ; [ DW_TAG_subprogram ] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] +!7 = !{i32 2, !"Dwarf Version", i32 2} +!8 = !{i32 2, !"Debug Info Version", i32 2} +!9 = !{!"clang version 3.6.0"} +!10 = !MDLocation(line: 2, column: 8, scope: !11) +!11 = !{!"0xb\002\003\000", !1, !4} ; [ DW_TAG_lexical_block ] +!12 = !MDLocation(line: 3, column: 9, scope: !13) +!13 = !{!"0xb\003\009\000", !1, !11} ; [ DW_TAG_lexical_block ] +!14 = !{!15, !15, i64 0} +!15 = !{!"int", !16, i64 0} +!16 = !{!"omnipotent char", !17, i64 0} +!17 = !{!"Simple C/C++ TBAA"} +!18 = !MDLocation(line: 3, column: 29, scope: !13) +!19 = !MDLocation(line: 4, column: 1, scope: !4) diff --git a/test/Transforms/LoopVectorize/control-flow.ll b/test/Transforms/LoopVectorize/control-flow.ll index e4ba77fa3daa..1882c3ff9a83 100644 --- a/test/Transforms/LoopVectorize/control-flow.ll +++ b/test/Transforms/LoopVectorize/control-flow.ll @@ -11,7 +11,7 @@ ; } ; CHECK: remark: source.cpp:5:9: loop not vectorized: loop control flow is not understood by vectorizer -; CHECK: remark: source.cpp:5:9: loop not vectorized: vectorization was not specified +; CHECK: remark: source.cpp:5:9: loop not vectorized: use -Rpass-analysis=loop-vectorize for more info ; CHECK: _Z4testPii ; CHECK-NOT: x i32> @@ -55,24 +55,24 @@ attributes #0 = { nounwind } !llvm.module.flags = !{!7, !8} !llvm.ident = !{!9} -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.5.0", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 2} -!1 = metadata !{metadata !"source.cpp", metadata !"."} -!2 = metadata !{} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"test", metadata !"test", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i32 (i32*, i32)* @_Z4testPii, null, null, metadata !2, i32 2} -!5 = metadata !{i32 786473, metadata !1} -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} -!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} -!8 = metadata !{i32 2, metadata !"Debug Info Version", i32 1} -!9 = metadata !{metadata !"clang version 3.5.0"} -!10 = metadata !{i32 3, i32 8, metadata !11, null} -!11 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 3, i32 0, i32 0} -!12 = metadata !{i32 5, i32 9, metadata !13, null} -!13 = metadata !{i32 786443, metadata !1, metadata !14, i32 5, i32 9, i32 0, i32 2} -!14 = metadata !{i32 786443, metadata !1, metadata !11, i32 4, i32 3, i32 0, i32 1} -!15 = metadata !{metadata !16, metadata !16, i64 0} -!16 = metadata !{metadata !"int", metadata !17, i64 0} -!17 = metadata !{metadata !"omnipotent char", metadata !18, i64 0} -!18 = metadata !{metadata !"Simple C/C++ TBAA"} -!19 = metadata !{i32 8, i32 7, metadata !13, null} -!20 = metadata !{i32 12, i32 3, metadata !4, null} +!0 = !{!"0x11\004\00clang version 3.5.0\001\00\006\00\002", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [./source.cpp] [DW_LANG_C_plus_plus] +!1 = !{!"source.cpp", !"."} +!2 = !{} +!3 = !{!4} +!4 = !{!"0x2e\00test\00test\00\001\000\001\000\006\00256\001\002", !1, !5, !6, null, i32 (i32*, i32)* @_Z4testPii, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [scope 2] [test] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [./source.cpp] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{i32 2, !"Dwarf Version", i32 2} +!8 = !{i32 2, !"Debug Info Version", i32 2} +!9 = !{!"clang version 3.5.0"} +!10 = !MDLocation(line: 3, column: 8, scope: !11) +!11 = !{!"0xb\003\003\000", !1, !4} ; [ DW_TAG_lexical_block ] +!12 = !MDLocation(line: 5, column: 9, scope: !13) +!13 = !{!"0xb\005\009\000", !1, !14} ; [ DW_TAG_lexical_block ] +!14 = !{!"0xb\004\003\000", !1, !11} ; [ DW_TAG_lexical_block ] +!15 = !{!16, !16, i64 0} +!16 = !{!"int", !17, i64 0} +!17 = !{!"omnipotent char", !18, i64 0} +!18 = !{!"Simple C/C++ TBAA"} +!19 = !MDLocation(line: 8, column: 7, scope: !13) +!20 = !MDLocation(line: 12, column: 3, scope: !4) diff --git a/test/Transforms/LoopVectorize/cpp-new-array.ll b/test/Transforms/LoopVectorize/cpp-new-array.ll index c8215a107de7..f32f610b1cd6 100644 --- a/test/Transforms/LoopVectorize/cpp-new-array.ll +++ b/test/Transforms/LoopVectorize/cpp-new-array.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/dbg.value.ll b/test/Transforms/LoopVectorize/dbg.value.ll index 2497b25ea1da..92d315481266 100644 --- a/test/Transforms/LoopVectorize/dbg.value.ll +++ b/test/Transforms/LoopVectorize/dbg.value.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -S -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine | FileCheck %s +; RUN: opt < %s -S -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine | FileCheck %s ; Make sure we vectorize with debugging turned on. 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" @@ -11,7 +11,7 @@ target triple = "x86_64-apple-macosx10.8.0" ; CHECK-LABEL: @test( define i32 @test() #0 { entry: - tail call void @llvm.dbg.value(metadata !1, i64 0, metadata !9), !dbg !18 + tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !9, metadata !{}), !dbg !18 br label %for.body, !dbg !18 for.body: @@ -25,7 +25,7 @@ for.body: %arrayidx4 = getelementptr inbounds [1024 x i32]* @A, i64 0, i64 %indvars.iv, !dbg !19 store i32 %add, i32* %arrayidx4, align 4, !dbg !19 %indvars.iv.next = add i64 %indvars.iv, 1, !dbg !18 - tail call void @llvm.dbg.value(metadata !{null}, i64 0, metadata !9), !dbg !18 + tail call void @llvm.dbg.value(metadata !{null}, i64 0, metadata !9, metadata !{}), !dbg !18 %lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !18 %exitcond = icmp ne i32 %lftr.wideiv, 1024, !dbg !18 br i1 %exitcond, label %for.body, label %for.end, !dbg !18 @@ -34,9 +34,9 @@ for.end: ret i32 0, !dbg !24 } -declare void @llvm.dbg.declare(metadata, metadata) #1 +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 -declare void @llvm.dbg.value(metadata, i64, metadata) #1 +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1 attributes #0 = { nounwind ssp uwtable "fp-contract-model"="standard" "no-frame-pointer-elim" "no-frame-pointer-elim-non-leaf" "relocation-model"="pic" "ssp-buffers-size"="8" } attributes #1 = { nounwind readnone } @@ -44,27 +44,27 @@ attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!26} -!0 = metadata !{i32 786449, metadata !25, i32 4, metadata !"clang", i1 true, metadata !"", i32 0, metadata !1, metadata !1, metadata !2, metadata !11, null, metadata !""} -!1 = metadata !{i32 0} -!2 = metadata !{metadata !3} -!3 = metadata !{i32 786478, metadata !25, metadata !4, metadata !"test", metadata !"test", metadata !"test", i32 5, metadata !5, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i32 ()* @test, null, null, metadata !8, i32 5} -!4 = metadata !{i32 786473, metadata !25} -!5 = metadata !{i32 786453, i32 0, null, i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !6, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!6 = metadata !{metadata !7} -!7 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} -!8 = metadata !{metadata !9} -!9 = metadata !{i32 786688, metadata !10, metadata !"i", metadata !4, i32 6, metadata !7, i32 0, i32 0} -!10 = metadata !{i32 786443, metadata !25, metadata !3, i32 6, i32 0, i32 0} -!11 = metadata !{metadata !12, metadata !16, metadata !17} -!12 = metadata !{i32 786484, i32 0, null, metadata !"A", metadata !"A", metadata !"", metadata !4, i32 1, metadata !13, i32 0, i32 1, [1024 x i32]* @A, null} -!13 = metadata !{i32 786433, null, null, null, i32 0, i64 32768, i64 32, i32 0, i32 0, metadata !7, metadata !14, i32 0, null, null, null} ; [ DW_TAG_array_type ] [line 0, size 32768, align 32, offset 0] [from int] -!14 = metadata !{metadata !15} -!15 = metadata !{i32 786465, i64 0, i64 1024} -!16 = metadata !{i32 786484, i32 0, null, metadata !"B", metadata !"B", metadata !"", metadata !4, i32 2, metadata !13, i32 0, i32 1, [1024 x i32]* @B, null} -!17 = metadata !{i32 786484, i32 0, null, metadata !"C", metadata !"C", metadata !"", metadata !4, i32 3, metadata !13, i32 0, i32 1, [1024 x i32]* @C, null} -!18 = metadata !{i32 6, i32 0, metadata !10, null} -!19 = metadata !{i32 7, i32 0, metadata !20, null} -!20 = metadata !{i32 786443, metadata !25, metadata !10, i32 6, i32 0, i32 1} -!24 = metadata !{i32 9, i32 0, metadata !3, null} -!25 = metadata !{metadata !"test", metadata !"/path/to/somewhere"} -!26 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x11\004\00clang\001\00\000\00\000", !25, !1, !1, !2, !11, null} ; [ DW_TAG_compile_unit ] +!1 = !{i32 0} +!2 = !{!3} +!3 = !{!"0x2e\00test\00test\00test\005\000\001\000\006\00256\001\005", !25, !4, !5, null, i32 ()* @test, null, null, !8} ; [ DW_TAG_subprogram ] +!4 = !{!"0x29", !25} ; [ DW_TAG_file_type ] +!5 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !6, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!6 = !{!7} +!7 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] +!8 = !{!9} +!9 = !{!"0x100\00i\006\000", !10, !4, !7} ; [ DW_TAG_auto_variable ] +!10 = !{!"0xb\006\000\000", !25, !3} ; [ DW_TAG_lexical_block ] +!11 = !{!12, !16, !17} +!12 = !{!"0x34\00A\00A\00\001\000\001", null, !4, !13, [1024 x i32]* @A, null} ; [ DW_TAG_variable ] +!13 = !{!"0x1\00\000\0032768\0032\000\000", null, null, !7, !14, i32 0, null, null, null} ; [ DW_TAG_array_type ] [line 0, size 32768, align 32, offset 0] [from int] +!14 = !{!15} +!15 = !{i32 786465, i64 0, i64 1024} +!16 = !{!"0x34\00B\00B\00\002\000\001", null, !4, !13, [1024 x i32]* @B, null} ; [ DW_TAG_variable ] +!17 = !{!"0x34\00C\00C\00\003\000\001", null, !4, !13, [1024 x i32]* @C, null} ; [ DW_TAG_variable ] +!18 = !MDLocation(line: 6, scope: !10) +!19 = !MDLocation(line: 7, scope: !20) +!20 = !{!"0xb\006\000\001", !25, !10} ; [ DW_TAG_lexical_block ] +!24 = !MDLocation(line: 9, scope: !3) +!25 = !{!"test", !"/path/to/somewhere"} +!26 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/LoopVectorize/debugloc.ll b/test/Transforms/LoopVectorize/debugloc.ll index bf0b4184b7a1..634bf79ddf0e 100644 --- a/test/Transforms/LoopVectorize/debugloc.ll +++ b/test/Transforms/LoopVectorize/debugloc.ll @@ -1,4 +1,4 @@ -; RUN: opt -S < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=2 | FileCheck %s +; RUN: opt -S < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=2 | 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" @@ -19,10 +19,10 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 define i32 @f(i32* nocapture %a, i32 %size) #0 { entry: - tail call void @llvm.dbg.value(metadata !{i32* %a}, i64 0, metadata !13), !dbg !19 - tail call void @llvm.dbg.value(metadata !{i32 %size}, i64 0, metadata !14), !dbg !19 - tail call void @llvm.dbg.value(metadata !2, i64 0, metadata !15), !dbg !20 - tail call void @llvm.dbg.value(metadata !2, i64 0, metadata !16), !dbg !21 + tail call void @llvm.dbg.value(metadata i32* %a, i64 0, metadata !13, metadata !{}), !dbg !19 + tail call void @llvm.dbg.value(metadata i32 %size, i64 0, metadata !14, metadata !{}), !dbg !19 + tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !15, metadata !{}), !dbg !20 + tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !16, metadata !{}), !dbg !21 %cmp4 = icmp eq i32 %size, 0, !dbg !21 br i1 %cmp4, label %for.end, label %for.body.lr.ph, !dbg !21 @@ -35,9 +35,9 @@ for.body: ; preds = %for.body.lr.ph, %fo %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv, !dbg !22 %0 = load i32* %arrayidx, align 4, !dbg !22 %add = add i32 %0, %sum.05, !dbg !22 - tail call void @llvm.dbg.value(metadata !{i32 %add.lcssa}, i64 0, metadata !15), !dbg !22 + tail call void @llvm.dbg.value(metadata i32 %add.lcssa, i64 0, metadata !15, metadata !{}), !dbg !22 %indvars.iv.next = add i64 %indvars.iv, 1, !dbg !21 - tail call void @llvm.dbg.value(metadata !{null}, i64 0, metadata !16), !dbg !21 + tail call void @llvm.dbg.value(metadata !{null}, i64 0, metadata !16, metadata !{}), !dbg !21 %lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !21 %exitcond = icmp ne i32 %lftr.wideiv, %size, !dbg !21 br i1 %exitcond, label %for.body, label %for.cond.for.end_crit_edge, !dbg !21 @@ -52,10 +52,10 @@ for.end: ; preds = %entry, %for.cond.fo } ; Function Attrs: nounwind readnone -declare void @llvm.dbg.declare(metadata, metadata) #1 +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 ; Function Attrs: nounwind readnone -declare void @llvm.dbg.value(metadata, i64, metadata) #1 +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1 attributes #0 = { nounwind readonly ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "unsafe-fp-math"="true" "use-soft-float"="false" } attributes #1 = { nounwind readnone } @@ -63,28 +63,28 @@ attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!18, !27} -!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.4 (trunk 185038) (llvm/trunk 185097)", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/Volumes/Data/backedup/dev/os/llvm/debug/-] [DW_LANG_C99] -!1 = metadata !{metadata !"-", metadata !"/Volumes/Data/backedup/dev/os/llvm/debug"} -!2 = metadata !{i32 0} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !5, metadata !6, metadata !"f", metadata !"f", metadata !"", i32 3, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i32 (i32*, i32)* @f, null, null, metadata !12, i32 3} ; [ DW_TAG_subprogram ] [line 3] [def] [f] -!5 = metadata !{metadata !"<stdin>", metadata !"/Volumes/Data/backedup/dev/os/llvm/debug"} -!6 = metadata !{i32 786473, metadata !5} ; [ DW_TAG_file_type ] [/Volumes/Data/backedup/dev/os/llvm/debug/<stdin>] -!7 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!8 = metadata !{metadata !9, metadata !10, metadata !11} -!9 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] -!10 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !9} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int] -!11 = metadata !{i32 786468, null, null, metadata !"unsigned int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 7} ; [ DW_TAG_base_type ] [unsigned int] [line 0, size 32, align 32, offset 0, enc DW_ATE_unsigned] -!12 = metadata !{metadata !13, metadata !14, metadata !15, metadata !16} -!13 = metadata !{i32 786689, metadata !4, metadata !"a", metadata !6, i32 16777219, metadata !10, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [a] [line 3] -!14 = metadata !{i32 786689, metadata !4, metadata !"size", metadata !6, i32 33554435, metadata !11, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [size] [line 3] -!15 = metadata !{i32 786688, metadata !4, metadata !"sum", metadata !6, i32 4, metadata !11, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [sum] [line 4] -!16 = metadata !{i32 786688, metadata !17, metadata !"i", metadata !6, i32 5, metadata !11, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [i] [line 5] -!17 = metadata !{i32 786443, metadata !5, metadata !4, i32 5, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [/Volumes/Data/backedup/dev/os/llvm/debug/<stdin>] -!18 = metadata !{i32 2, metadata !"Dwarf Version", i32 3} -!19 = metadata !{i32 3, i32 0, metadata !4, null} -!20 = metadata !{i32 4, i32 0, metadata !4, null} -!21 = metadata !{i32 5, i32 0, metadata !17, null} -!22 = metadata !{i32 6, i32 0, metadata !17, null} -!26 = metadata !{i32 7, i32 0, metadata !4, null} -!27 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x11\0012\00clang version 3.4 (trunk 185038) (llvm/trunk 185097)\001\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [/Volumes/Data/backedup/dev/os/llvm/debug/-] [DW_LANG_C99] +!1 = !{!"-", !"/Volumes/Data/backedup/dev/os/llvm/debug"} +!2 = !{i32 0} +!3 = !{!4} +!4 = !{!"0x2e\00f\00f\00\003\000\001\000\006\00256\001\003", !5, !6, !7, null, i32 (i32*, i32)* @f, null, null, !12} ; [ DW_TAG_subprogram ] [line 3] [def] [f] +!5 = !{!"<stdin>", !"/Volumes/Data/backedup/dev/os/llvm/debug"} +!6 = !{!"0x29", !5} ; [ DW_TAG_file_type ] [/Volumes/Data/backedup/dev/os/llvm/debug/<stdin>] +!7 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !8, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!8 = !{!9, !10, !11} +!9 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!10 = !{!"0xf\00\000\0064\0064\000\000", null, null, !9} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int] +!11 = !{!"0x24\00unsigned int\000\0032\0032\000\000\007", null, null} ; [ DW_TAG_base_type ] [unsigned int] [line 0, size 32, align 32, offset 0, enc DW_ATE_unsigned] +!12 = !{!13, !14, !15, !16} +!13 = !{!"0x101\00a\0016777219\000", !4, !6, !10} ; [ DW_TAG_arg_variable ] [a] [line 3] +!14 = !{!"0x101\00size\0033554435\000", !4, !6, !11} ; [ DW_TAG_arg_variable ] [size] [line 3] +!15 = !{!"0x100\00sum\004\000", !4, !6, !11} ; [ DW_TAG_auto_variable ] [sum] [line 4] +!16 = !{!"0x100\00i\005\000", !17, !6, !11} ; [ DW_TAG_auto_variable ] [i] [line 5] +!17 = !{!"0xb\005\000\000", !5, !4} ; [ DW_TAG_lexical_block ] [/Volumes/Data/backedup/dev/os/llvm/debug/<stdin>] +!18 = !{i32 2, !"Dwarf Version", i32 3} +!19 = !MDLocation(line: 3, scope: !4) +!20 = !MDLocation(line: 4, scope: !4) +!21 = !MDLocation(line: 5, scope: !17) +!22 = !MDLocation(line: 6, scope: !17) +!26 = !MDLocation(line: 7, scope: !4) +!27 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/LoopVectorize/duplicated-metadata.ll b/test/Transforms/LoopVectorize/duplicated-metadata.ll new file mode 100644 index 000000000000..bf2f899dff04 --- /dev/null +++ b/test/Transforms/LoopVectorize/duplicated-metadata.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -loop-vectorize -S 2>&1 | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; This test makes sure we don't duplicate the loop vectorizer's metadata +; while marking them as already vectorized (by setting width = 1), even +; at lower optimization levels, where no extra cleanup is done + +define void @_Z3fooPf(float* %a) { +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %arrayidx = getelementptr inbounds float* %a, i64 %indvars.iv + %p = load float* %arrayidx, align 4 + %mul = fmul float %p, 2.000000e+00 + store float %mul, float* %arrayidx, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond = icmp eq i64 %indvars.iv.next, 1024 + br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0 + +for.end: ; preds = %for.body + ret void +} + +!0 = !{!0, !1} +!1 = !{!"llvm.loop.vectorize.width", i32 4} +; CHECK-NOT: !{metadata !"llvm.loop.vectorize.width", i32 4} +; CHECK: !{!"llvm.loop.interleave.count", i32 1} diff --git a/test/Transforms/LoopVectorize/ee-crash.ll b/test/Transforms/LoopVectorize/ee-crash.ll index 8a4f8ce3c122..a3c0bb89b128 100644 --- a/test/Transforms/LoopVectorize/ee-crash.ll +++ b/test/Transforms/LoopVectorize/ee-crash.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/exact.ll b/test/Transforms/LoopVectorize/exact.ll new file mode 100644 index 000000000000..0a8fbf337347 --- /dev/null +++ b/test/Transforms/LoopVectorize/exact.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -loop-vectorize -force-vector-width=4 -S | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.9.0" + +; CHECK-LABEL: @lshr_exact( +; CHECK: lshr exact <4 x i32> +define void @lshr_exact(i32* %x) { +entry: + br label %for.body + +for.body: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] + %arrayidx = getelementptr inbounds i32* %x, i64 %iv + %0 = load i32* %arrayidx, align 4 + %conv1 = lshr exact i32 %0, 1 + store i32 %conv1, i32* %arrayidx, align 4 + %iv.next = add nuw nsw i64 %iv, 1 + %exitcond = icmp eq i64 %iv.next, 256 + br i1 %exitcond, label %for.end, label %for.body + +for.end: + ret void +} diff --git a/test/Transforms/LoopVectorize/flags.ll b/test/Transforms/LoopVectorize/flags.ll index 21d09372d546..0fc55c897310 100644 --- a/test/Transforms/LoopVectorize/flags.ll +++ b/test/Transforms/LoopVectorize/flags.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/float-reduction.ll b/test/Transforms/LoopVectorize/float-reduction.ll index 0dfbab07279a..0f064ee2dc85 100644 --- a/test/Transforms/LoopVectorize/float-reduction.ll +++ b/test/Transforms/LoopVectorize/float-reduction.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" @@ -23,3 +23,25 @@ for.body: ; preds = %for.body, %entry for.end: ; preds = %for.body ret float %add } + +;CHECK-LABEL: @foosub( +;CHECK: fsub fast <4 x float> +;CHECK: ret +define float @foosub(float* nocapture %A, i32* nocapture %n) nounwind uwtable readonly ssp { +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %sum.04 = phi float [ 0.000000e+00, %entry ], [ %sub, %for.body ] + %arrayidx = getelementptr inbounds float* %A, i64 %indvars.iv + %0 = load float* %arrayidx, align 4 + %sub = fsub fast float %sum.04, %0 + %indvars.iv.next = add i64 %indvars.iv, 1 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32 + %exitcond = icmp eq i32 %lftr.wideiv, 200 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret float %sub +} diff --git a/test/Transforms/LoopVectorize/funcall.ll b/test/Transforms/LoopVectorize/funcall.ll index f1f068c43db3..e03534fbac37 100644 --- a/test/Transforms/LoopVectorize/funcall.ll +++ b/test/Transforms/LoopVectorize/funcall.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -loop-vectorize -force-vector-width=2 -force-vector-unroll=1 < %s | FileCheck %s +; RUN: opt -S -loop-vectorize -force-vector-width=2 -force-vector-interleave=1 < %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" diff --git a/test/Transforms/LoopVectorize/gcc-examples.ll b/test/Transforms/LoopVectorize/gcc-examples.ll index b6cde5d00f5e..6c8af0bcd7c9 100644 --- a/test/Transforms/LoopVectorize/gcc-examples.ll +++ b/test/Transforms/LoopVectorize/gcc-examples.ll @@ -1,5 +1,5 @@ -; RUN: opt < %s -basicaa -loop-vectorize -force-vector-width=4 -force-vector-unroll=1 -dce -instcombine -S | FileCheck %s -; RUN: opt < %s -basicaa -loop-vectorize -force-vector-width=4 -force-vector-unroll=4 -dce -instcombine -S | FileCheck %s -check-prefix=UNROLL +; RUN: opt < %s -basicaa -loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -basicaa -loop-vectorize -force-vector-width=4 -force-vector-interleave=4 -dce -instcombine -S | FileCheck %s -check-prefix=UNROLL 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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/global_alias.ll b/test/Transforms/LoopVectorize/global_alias.ll index d64d67f6a5b1..3f11ce8bf213 100644 --- a/test/Transforms/LoopVectorize/global_alias.ll +++ b/test/Transforms/LoopVectorize/global_alias.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -O1 -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -O1 -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %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-v64:64:64-v128:64:128-a0:0:64-n32-S64" diff --git a/test/Transforms/LoopVectorize/hoist-loads.ll b/test/Transforms/LoopVectorize/hoist-loads.ll index 765e14d6985b..d0b27f1eae7c 100644 --- a/test/Transforms/LoopVectorize/hoist-loads.ll +++ b/test/Transforms/LoopVectorize/hoist-loads.ll @@ -1,4 +1,4 @@ -; RUN: opt -loop-vectorize -force-vector-width=2 -force-vector-unroll=1 -S < %s | FileCheck %s +; RUN: opt -loop-vectorize -force-vector-width=2 -force-vector-interleave=1 -S < %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" diff --git a/test/Transforms/LoopVectorize/i8-induction.ll b/test/Transforms/LoopVectorize/i8-induction.ll index 2a0e82645494..90e3ec00cde2 100644 --- a/test/Transforms/LoopVectorize/i8-induction.ll +++ b/test/Transforms/LoopVectorize/i8-induction.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/if-conv-crash.ll b/test/Transforms/LoopVectorize/if-conv-crash.ll index f8f2cf1fff4b..67910bf6d544 100644 --- a/test/Transforms/LoopVectorize/if-conv-crash.ll +++ b/test/Transforms/LoopVectorize/if-conv-crash.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -enable-if-conversion +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -enable-if-conversion 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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/if-conversion-nest.ll b/test/Transforms/LoopVectorize/if-conversion-nest.ll index 92cb06e5e525..b5ac8fca23b3 100644 --- a/test/Transforms/LoopVectorize/if-conversion-nest.ll +++ b/test/Transforms/LoopVectorize/if-conversion-nest.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -enable-if-conversion -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -enable-if-conversion -dce -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" diff --git a/test/Transforms/LoopVectorize/if-conversion-reduction.ll b/test/Transforms/LoopVectorize/if-conversion-reduction.ll index 8cb703cdfa4b..455699c78030 100644 --- a/test/Transforms/LoopVectorize/if-conversion-reduction.ll +++ b/test/Transforms/LoopVectorize/if-conversion-reduction.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -enable-if-conversion -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -enable-if-conversion -dce -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" target triple = "x86_64-apple-macosx10.9.0" diff --git a/test/Transforms/LoopVectorize/if-conversion.ll b/test/Transforms/LoopVectorize/if-conversion.ll index 6e3e8ed27853..9e185284919a 100644 --- a/test/Transforms/LoopVectorize/if-conversion.ll +++ b/test/Transforms/LoopVectorize/if-conversion.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -enable-if-conversion -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -enable-if-conversion -dce -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" target triple = "x86_64-apple-macosx10.9.0" diff --git a/test/Transforms/LoopVectorize/if-pred-stores.ll b/test/Transforms/LoopVectorize/if-pred-stores.ll index 7b0e181c845f..c6067e01ee21 100644 --- a/test/Transforms/LoopVectorize/if-pred-stores.ll +++ b/test/Transforms/LoopVectorize/if-pred-stores.ll @@ -1,5 +1,5 @@ -; RUN: opt -S -vectorize-num-stores-pred=1 -force-vector-width=1 -force-vector-unroll=2 -loop-vectorize < %s | FileCheck %s --check-prefix=UNROLL -; RUN: opt -S -vectorize-num-stores-pred=1 -force-vector-width=2 -force-vector-unroll=1 -loop-vectorize -enable-cond-stores-vec < %s | FileCheck %s --check-prefix=VEC +; RUN: opt -S -vectorize-num-stores-pred=1 -force-vector-width=1 -force-vector-interleave=2 -loop-vectorize < %s | FileCheck %s --check-prefix=UNROLL +; RUN: opt -S -vectorize-num-stores-pred=1 -force-vector-width=2 -force-vector-interleave=1 -loop-vectorize -enable-cond-stores-vec < %s | FileCheck %s --check-prefix=VEC target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.9.0" diff --git a/test/Transforms/LoopVectorize/incorrect-dom-info.ll b/test/Transforms/LoopVectorize/incorrect-dom-info.ll index 624ee7e50597..b8624fd00774 100644 --- a/test/Transforms/LoopVectorize/incorrect-dom-info.ll +++ b/test/Transforms/LoopVectorize/incorrect-dom-info.ll @@ -139,4 +139,4 @@ attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-po !llvm.ident = !{!0} -!0 = metadata !{metadata !"clang version 3.6.0 "} +!0 = !{!"clang version 3.6.0 "} diff --git a/test/Transforms/LoopVectorize/increment.ll b/test/Transforms/LoopVectorize/increment.ll index 71bedb7334ac..067a76b51ad0 100644 --- a/test/Transforms/LoopVectorize/increment.ll +++ b/test/Transforms/LoopVectorize/increment.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/induction.ll b/test/Transforms/LoopVectorize/induction.ll index 7dabcb2ba04f..3f3491835b54 100644 --- a/test/Transforms/LoopVectorize/induction.ll +++ b/test/Transforms/LoopVectorize/induction.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=2 -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=2 -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" @@ -28,7 +28,7 @@ for.end: ret void } -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=2 -instcombine -S | FileCheck %s --check-prefix=IND +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=2 -instcombine -S | FileCheck %s --check-prefix=IND ; Make sure we remove unneeded vectorization of induction variables. ; In order for instcombine to cleanup the vectorized induction variables that we diff --git a/test/Transforms/LoopVectorize/induction_plus.ll b/test/Transforms/LoopVectorize/induction_plus.ll index 9c8201ab7805..ce64c5b620d5 100644 --- a/test/Transforms/LoopVectorize/induction_plus.ll +++ b/test/Transforms/LoopVectorize/induction_plus.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/intrinsic.ll b/test/Transforms/LoopVectorize/intrinsic.ll index 7dfaf03b0f2d..d48731a07436 100644 --- a/test/Transforms/LoopVectorize/intrinsic.ll +++ b/test/Transforms/LoopVectorize/intrinsic.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-unknown-linux-gnu" @@ -1192,3 +1192,59 @@ for.body: ; preds = %entry, %for.body for.end: ; preds = %for.body, %entry ret void } + +declare float @llvm.minnum.f32(float, float) nounwind readnone + +;CHECK-LABEL: @minnum_f32( +;CHECK: llvm.minnum.v4f32 +;CHECK: ret void +define void @minnum_f32(i32 %n, float* noalias %y, float* noalias %x, float* noalias %z) nounwind uwtable { +entry: + %cmp9 = icmp sgt i32 %n, 0 + br i1 %cmp9, label %for.body, label %for.end + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds float* %y, i64 %indvars.iv + %0 = load float* %arrayidx, align 4 + %arrayidx2 = getelementptr inbounds float* %z, i64 %indvars.iv + %1 = load float* %arrayidx2, align 4 + %call = tail call float @llvm.minnum.f32(float %0, float %1) nounwind readnone + %arrayidx4 = getelementptr inbounds float* %x, i64 %indvars.iv + store float %call, float* %arrayidx4, align 4 + %indvars.iv.next = add i64 %indvars.iv, 1 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32 + %exitcond = icmp eq i32 %lftr.wideiv, %n + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body, %entry + ret void +} + +declare float @llvm.maxnum.f32(float, float) nounwind readnone + +;CHECK-LABEL: @maxnum_f32( +;CHECK: llvm.maxnum.v4f32 +;CHECK: ret void +define void @maxnum_f32(i32 %n, float* noalias %y, float* noalias %x, float* noalias %z) nounwind uwtable { +entry: + %cmp9 = icmp sgt i32 %n, 0 + br i1 %cmp9, label %for.body, label %for.end + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds float* %y, i64 %indvars.iv + %0 = load float* %arrayidx, align 4 + %arrayidx2 = getelementptr inbounds float* %z, i64 %indvars.iv + %1 = load float* %arrayidx2, align 4 + %call = tail call float @llvm.maxnum.f32(float %0, float %1) nounwind readnone + %arrayidx4 = getelementptr inbounds float* %x, i64 %indvars.iv + store float %call, float* %arrayidx4, align 4 + %indvars.iv.next = add i64 %indvars.iv, 1 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32 + %exitcond = icmp eq i32 %lftr.wideiv, %n + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body, %entry + ret void +} diff --git a/test/Transforms/LoopVectorize/lcssa-crash.ll b/test/Transforms/LoopVectorize/lcssa-crash.ll index de6be548490c..68cc74ed7098 100644 --- a/test/Transforms/LoopVectorize/lcssa-crash.ll +++ b/test/Transforms/LoopVectorize/lcssa-crash.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 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" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/Transforms/LoopVectorize/lifetime.ll b/test/Transforms/LoopVectorize/lifetime.ll index 4f6f3b820a43..ba36cc4f7aa4 100644 --- a/test/Transforms/LoopVectorize/lifetime.ll +++ b/test/Transforms/LoopVectorize/lifetime.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -loop-vectorize -force-vector-width=2 -force-vector-unroll=1 < %s | FileCheck %s +; RUN: opt -S -loop-vectorize -force-vector-width=2 -force-vector-interleave=1 < %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" diff --git a/test/Transforms/LoopVectorize/loop-vect-memdep.ll b/test/Transforms/LoopVectorize/loop-vect-memdep.ll new file mode 100644 index 000000000000..e2c7524238d1 --- /dev/null +++ b/test/Transforms/LoopVectorize/loop-vect-memdep.ll @@ -0,0 +1,26 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +; RUN: opt < %s -S -loop-vectorize -debug-only=loop-vectorize 2>&1 | FileCheck %s +; REQUIRES: asserts +; CHECK: LV: Can't vectorize due to memory conflicts + +define void @test_loop_novect(double** %arr, i64 %n) { +for.body.lr.ph: + %t = load double** %arr, align 8 + br label %for.body + +for.body: ; preds = %for.body, %for.body.lr.ph + %i = phi i64 [ 0, %for.body.lr.ph ], [ %i.next, %for.body ] + %a = getelementptr inbounds double* %t, i64 %i + %i.next = add nuw nsw i64 %i, 1 + %a.next = getelementptr inbounds double* %t, i64 %i.next + %t1 = load double* %a, align 8 + %t2 = load double* %a.next, align 8 + store double %t1, double* %a.next, align 8 + store double %t2, double* %a, align 8 + %c = icmp eq i64 %i, %n + br i1 %c, label %final, label %for.body + +final: ; preds = %for.body + ret void +} diff --git a/test/Transforms/LoopVectorize/memdep.ll b/test/Transforms/LoopVectorize/memdep.ll index 21cb703ba47c..f857e800bea7 100644 --- a/test/Transforms/LoopVectorize/memdep.ll +++ b/test/Transforms/LoopVectorize/memdep.ll @@ -1,5 +1,5 @@ -; RUN: opt < %s -loop-vectorize -force-vector-width=2 -force-vector-unroll=1 -S | FileCheck %s -; RUN: opt < %s -loop-vectorize -force-vector-width=4 -force-vector-unroll=1 -S | FileCheck %s -check-prefix=WIDTH +; RUN: opt < %s -loop-vectorize -force-vector-width=2 -force-vector-interleave=1 -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S | FileCheck %s -check-prefix=WIDTH 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" diff --git a/test/Transforms/LoopVectorize/metadata-unroll.ll b/test/Transforms/LoopVectorize/metadata-unroll.ll index 848f1f9601b9..36a231454f08 100644 --- a/test/Transforms/LoopVectorize/metadata-unroll.ll +++ b/test/Transforms/LoopVectorize/metadata-unroll.ll @@ -37,5 +37,5 @@ define void @inc(i32 %n) nounwind uwtable noinline ssp { ret void } -!0 = metadata !{metadata !0, metadata !1} -!1 = metadata !{metadata !"llvm.loop.interleave.count", i32 2} +!0 = !{!0, !1} +!1 = !{!"llvm.loop.interleave.count", i32 2} diff --git a/test/Transforms/LoopVectorize/metadata-width.ll b/test/Transforms/LoopVectorize/metadata-width.ll index 87de655da6f2..dee4feedd6b8 100644 --- a/test/Transforms/LoopVectorize/metadata-width.ll +++ b/test/Transforms/LoopVectorize/metadata-width.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -dce -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" target triple = "x86_64-unknown-linux-gnu" @@ -27,5 +27,5 @@ for.end: ; preds = %for.body, %entry attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } -!0 = metadata !{metadata !0, metadata !1} -!1 = metadata !{metadata !"llvm.loop.vectorize.width", i32 8} +!0 = !{!0, !1} +!1 = !{!"llvm.loop.vectorize.width", i32 8} diff --git a/test/Transforms/LoopVectorize/metadata.ll b/test/Transforms/LoopVectorize/metadata.ll index bdcf1c9fb229..a258f7c06c07 100644 --- a/test/Transforms/LoopVectorize/metadata.ll +++ b/test/Transforms/LoopVectorize/metadata.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -27,18 +27,18 @@ for.end: ; preds = %for.body ; CHECK: store <4 x i32> %{{.*}}, <4 x i32>* %{{.*}}, align 4, !tbaa ![[TINT:[0-9]+]] ; CHECK: ret i32 0 -; CHECK-DAG: ![[TFLT]] = metadata !{metadata ![[TFLT1:[0-9]+]] -; CHECK-DAG: ![[TFLT1]] = metadata !{metadata !"float" +; CHECK-DAG: ![[TFLT]] = !{![[TFLT1:[0-9]+]] +; CHECK-DAG: ![[TFLT1]] = !{!"float" -; CHECK-DAG: ![[TINT]] = metadata !{metadata ![[TINT1:[0-9]+]] -; CHECK-DAG: ![[TINT1]] = metadata !{metadata !"int" +; CHECK-DAG: ![[TINT]] = !{![[TINT1:[0-9]+]] +; CHECK-DAG: ![[TINT1]] = !{!"int" attributes #0 = { nounwind uwtable } -!0 = metadata !{metadata !1, metadata !1, i64 0} -!1 = metadata !{metadata !"float", metadata !2, i64 0} -!2 = metadata !{metadata !"omnipotent char", metadata !3, i64 0} -!3 = metadata !{metadata !"Simple C/C++ TBAA"} -!4 = metadata !{metadata !5, metadata !5, i64 0} -!5 = metadata !{metadata !"int", metadata !2, i64 0} +!0 = !{!1, !1, i64 0} +!1 = !{!"float", !2, i64 0} +!2 = !{!"omnipotent char", !3, i64 0} +!3 = !{!"Simple C/C++ TBAA"} +!4 = !{!5, !5, i64 0} +!5 = !{!"int", !2, i64 0} diff --git a/test/Transforms/LoopVectorize/minmax_reduction.ll b/test/Transforms/LoopVectorize/minmax_reduction.ll index 0e47260984f2..1984cdd892d1 100644 --- a/test/Transforms/LoopVectorize/minmax_reduction.ll +++ b/test/Transforms/LoopVectorize/minmax_reduction.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -loop-vectorize -dce -instcombine -force-vector-width=2 -force-vector-unroll=1 < %s | FileCheck %s +; RUN: opt -S -loop-vectorize -dce -instcombine -force-vector-width=2 -force-vector-interleave=1 < %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" @@ -516,7 +516,7 @@ for.end: } ; CHECK-LABEL: @unordered_max_red_float( -; CHECK: fcmp ugt <2 x float> +; CHECK: fcmp ole <2 x float> ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp ogt <2 x float> @@ -542,7 +542,7 @@ for.end: } ; CHECK-LABEL: @unordered_max_red_float_ge( -; CHECK: fcmp uge <2 x float> +; CHECK: fcmp olt <2 x float> ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp ogt <2 x float> @@ -568,7 +568,7 @@ for.end: } ; CHECK-LABEL: @inverted_unordered_max_red_float( -; CHECK: fcmp ult <2 x float> +; CHECK: fcmp oge <2 x float> ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp ogt <2 x float> @@ -594,7 +594,7 @@ for.end: } ; CHECK-LABEL: @inverted_unordered_max_red_float_le( -; CHECK: fcmp ule <2 x float> +; CHECK: fcmp ogt <2 x float> ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp ogt <2 x float> @@ -727,7 +727,7 @@ for.end: } ; CHECK-LABEL: @unordered_min_red_float( -; CHECK: fcmp ult <2 x float> +; CHECK: fcmp oge <2 x float> ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp olt <2 x float> @@ -753,7 +753,7 @@ for.end: } ; CHECK-LABEL: @unordered_min_red_float_le( -; CHECK: fcmp ule <2 x float> +; CHECK: fcmp ogt <2 x float> ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp olt <2 x float> @@ -779,7 +779,7 @@ for.end: } ; CHECK-LABEL: @inverted_unordered_min_red_float( -; CHECK: fcmp ugt <2 x float> +; CHECK: fcmp ole <2 x float> ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp olt <2 x float> @@ -805,7 +805,7 @@ for.end: } ; CHECK-LABEL: @inverted_unordered_min_red_float_ge( -; CHECK: fcmp uge <2 x float> +; CHECK: fcmp olt <2 x float> ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp olt <2 x float> diff --git a/test/Transforms/LoopVectorize/multi-use-reduction-bug.ll b/test/Transforms/LoopVectorize/multi-use-reduction-bug.ll index 88a29c50df5a..cd022adc9399 100644 --- a/test/Transforms/LoopVectorize/multi-use-reduction-bug.ll +++ b/test/Transforms/LoopVectorize/multi-use-reduction-bug.ll @@ -1,4 +1,4 @@ -; RUN: opt -indvars -loop-vectorize -force-vector-width=2 -force-vector-unroll=1 -S < %s | FileCheck %s +; RUN: opt -indvars -loop-vectorize -force-vector-width=2 -force-vector-interleave=1 -S < %s | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.9.0" diff --git a/test/Transforms/LoopVectorize/multiple-address-spaces.ll b/test/Transforms/LoopVectorize/multiple-address-spaces.ll index d64662838e00..bb2af1e57ccc 100644 --- a/test/Transforms/LoopVectorize/multiple-address-spaces.ll +++ b/test/Transforms/LoopVectorize/multiple-address-spaces.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basicaa -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -basicaa -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s ; From a simple program with two address spaces: ; char Y[4*10000] __attribute__((address_space(1))); diff --git a/test/Transforms/LoopVectorize/no_array_bounds.ll b/test/Transforms/LoopVectorize/no_array_bounds.ll index 240b1b5d49dc..d3bd755e6cf1 100644 --- a/test/Transforms/LoopVectorize/no_array_bounds.ll +++ b/test/Transforms/LoopVectorize/no_array_bounds.ll @@ -72,30 +72,30 @@ attributes #0 = { nounwind } !llvm.module.flags = !{!7, !8} !llvm.ident = !{!9} -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.5.0", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 2} -!1 = metadata !{metadata !"no_array_bounds.cpp", metadata !"."} -!2 = metadata !{} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"test", metadata !"test", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (i32*, i32*, i32)* @_Z4testPiS_i, null, null, metadata !2, i32 2} -!5 = metadata !{i32 786473, metadata !1} -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} -!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} -!8 = metadata !{i32 2, metadata !"Debug Info Version", i32 1} -!9 = metadata !{metadata !"clang version 3.5.0"} -!10 = metadata !{i32 4, i32 8, metadata !11, null} -!11 = metadata !{i32 786443, metadata !1, metadata !4, i32 4, i32 3, i32 0, i32 0} -!12 = metadata !{metadata !12, metadata !13} -!13 = metadata !{metadata !"llvm.loop.vectorize.enable", i1 true} -!14 = metadata !{i32 5, i32 5, metadata !15, null} -!15 = metadata !{i32 786443, metadata !1, metadata !11, i32 4, i32 36, i32 0, i32 1} -!16 = metadata !{i32 9, i32 8, metadata !17, null} -!17 = metadata !{i32 786443, metadata !1, metadata !4, i32 9, i32 3, i32 0, i32 2} -!18 = metadata !{metadata !18, metadata !13, metadata !19} -!19 = metadata !{metadata !"llvm.loop.vectorize.width", i32 1} -!20 = metadata !{i32 10, i32 5, metadata !21, null} -!21 = metadata !{i32 786443, metadata !1, metadata !17, i32 9, i32 36, i32 0, i32 3} -!22 = metadata !{metadata !23, metadata !23, i64 0} -!23 = metadata !{metadata !"int", metadata !24, i64 0} -!24 = metadata !{metadata !"omnipotent char", metadata !25, i64 0} -!25 = metadata !{metadata !"Simple C/C++ TBAA"} -!26 = metadata !{i32 12, i32 1, metadata !4, null} +!0 = !{!"0x11\004\00clang version 3.5.0\001\00\000\00\002", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] +!1 = !{!"no_array_bounds.cpp", !"."} +!2 = !{} +!3 = !{!4} +!4 = !{!"0x2e\00test\00test\00\001\000\001\000\006\00256\001\002", !1, !5, !6, null, void (i32*, i32*, i32)* @_Z4testPiS_i, null, null, !2} ; [ DW_TAG_subprogram ] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] +!7 = !{i32 2, !"Dwarf Version", i32 2} +!8 = !{i32 2, !"Debug Info Version", i32 2} +!9 = !{!"clang version 3.5.0"} +!10 = !MDLocation(line: 4, column: 8, scope: !11) +!11 = !{!"0xb\004\003\000", !1, !4} ; [ DW_TAG_lexical_block ] +!12 = !{!12, !13} +!13 = !{!"llvm.loop.vectorize.enable", i1 true} +!14 = !MDLocation(line: 5, column: 5, scope: !15) +!15 = !{!"0xb\004\0036\000", !1, !11} ; [ DW_TAG_lexical_block ] +!16 = !MDLocation(line: 9, column: 8, scope: !17) +!17 = !{!"0xb\009\003\000", !1, !4} ; [ DW_TAG_lexical_block ] +!18 = !{!18, !13, !19} +!19 = !{!"llvm.loop.vectorize.width", i32 1} +!20 = !MDLocation(line: 10, column: 5, scope: !21) +!21 = !{!"0xb\009\0036\000", !1, !17} ; [ DW_TAG_lexical_block ] +!22 = !{!23, !23, i64 0} +!23 = !{!"int", !24, i64 0} +!24 = !{!"omnipotent char", !25, i64 0} +!25 = !{!"Simple C/C++ TBAA"} +!26 = !MDLocation(line: 12, column: 1, scope: !4) diff --git a/test/Transforms/LoopVectorize/no_idiv_reduction.ll b/test/Transforms/LoopVectorize/no_idiv_reduction.ll index 295fcabb0b29..5c721a6806d9 100644 --- a/test/Transforms/LoopVectorize/no_idiv_reduction.ll +++ b/test/Transforms/LoopVectorize/no_idiv_reduction.ll @@ -1,4 +1,4 @@ -; RUN: opt -loop-vectorize -force-vector-width=2 -force-vector-unroll=1 -S < %s | FileCheck %s +; RUN: opt -loop-vectorize -force-vector-width=2 -force-vector-interleave=1 -S < %s | FileCheck %s @a = common global [128 x i32] zeroinitializer, align 16 ;; Must not vectorize division reduction. Division is lossy. diff --git a/test/Transforms/LoopVectorize/no_int_induction.ll b/test/Transforms/LoopVectorize/no_int_induction.ll index e572d1a884ca..1275915f5e36 100644 --- a/test/Transforms/LoopVectorize/no_int_induction.ll +++ b/test/Transforms/LoopVectorize/no_int_induction.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s ; int __attribute__((noinline)) sum_array(int *A, int n) { ; return std::accumulate(A, A + n, 0); diff --git a/test/Transforms/LoopVectorize/no_outside_user.ll b/test/Transforms/LoopVectorize/no_outside_user.ll index 1f891ad2c4fa..bcd29c1a439a 100644 --- a/test/Transforms/LoopVectorize/no_outside_user.ll +++ b/test/Transforms/LoopVectorize/no_outside_user.ll @@ -1,4 +1,7 @@ -; RUN: opt -S -loop-vectorize -force-vector-unroll=1 -force-vector-width=2 < %s | FileCheck %s +; RUN: opt -S -loop-vectorize -force-vector-interleave=1 -force-vector-width=2 -pass-remarks-analysis=loop-vectorize < %s 2>&1 | FileCheck %s + +; CHECK: remark: {{.*}}: loop not vectorized: value could not be identified as an induction or reduction variable +; CHECK: remark: {{.*}}: loop not vectorized: use of induction value outside of the loop is not handled by vectorizer 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:32:32-n8:16:32-S128" diff --git a/test/Transforms/LoopVectorize/no_switch.ll b/test/Transforms/LoopVectorize/no_switch.ll index 8f654e41d4c8..64aab37592f6 100644 --- a/test/Transforms/LoopVectorize/no_switch.ll +++ b/test/Transforms/LoopVectorize/no_switch.ll @@ -1,7 +1,7 @@ ; RUN: opt < %s -loop-vectorize -force-vector-width=4 -S -pass-remarks-missed='loop-vectorize' -pass-remarks-analysis='loop-vectorize' 2>&1 | FileCheck %s ; CHECK: remark: source.cpp:4:5: loop not vectorized: loop contains a switch statement -; CHECK: remark: source.cpp:4:5: loop not vectorized: vectorization is explicitly enabled with width 4 +; CHECK: remark: source.cpp:4:5: loop not vectorized: use -Rpass-analysis=loop-vectorize for more info (Force=true, Vector Width=4) ; CHECK: warning: source.cpp:4:5: loop not vectorized: failed explicitly specified loop vectorization ; CHECK: _Z11test_switchPii @@ -59,28 +59,28 @@ attributes #0 = { nounwind } !llvm.module.flags = !{!7, !8} !llvm.ident = !{!9} -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.5.0", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 2} -!1 = metadata !{metadata !"source.cpp", metadata !"."} -!2 = metadata !{} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"test_switch", metadata !"test_switch", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (i32*, i32)* @_Z11test_switchPii, null, null, metadata !2, i32 1} -!5 = metadata !{i32 786473, metadata !1} -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} -!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} -!8 = metadata !{i32 2, metadata !"Debug Info Version", i32 1} -!9 = metadata !{metadata !"clang version 3.5.0"} -!10 = metadata !{i32 3, i32 8, metadata !11, null} -!11 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 3, i32 0, i32 0} -!12 = metadata !{metadata !12, metadata !13, metadata !13} -!13 = metadata !{metadata !"llvm.loop.vectorize.enable", i1 true} -!14 = metadata !{i32 4, i32 5, metadata !15, null} -!15 = metadata !{i32 786443, metadata !1, metadata !11, i32 3, i32 36, i32 0, i32 1} -!16 = metadata !{metadata !17, metadata !17, i64 0} -!17 = metadata !{metadata !"int", metadata !18, i64 0} -!18 = metadata !{metadata !"omnipotent char", metadata !19, i64 0} -!19 = metadata !{metadata !"Simple C/C++ TBAA"} -!20 = metadata !{i32 6, i32 7, metadata !21, null} -!21 = metadata !{i32 786443, metadata !1, metadata !15, i32 4, i32 18, i32 0, i32 2} -!22 = metadata !{i32 7, i32 5, metadata !21, null} -!23 = metadata !{i32 9, i32 7, metadata !21, null} -!24 = metadata !{i32 14, i32 1, metadata !4, null} +!0 = !{!"0x11\004\00clang version 3.5.0\001\00\006\00\002", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [./source.cpp] [DW_LANG_C_plus_plus] +!1 = !{!"source.cpp", !"."} +!2 = !{} +!3 = !{!4} +!4 = !{!"0x2e\00test_switch\00test_switch\00\001\000\001\000\006\00256\001\001", !1, !5, !6, null, void (i32*, i32)* @_Z11test_switchPii, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [test_switch] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [./source.cpp] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{i32 2, !"Dwarf Version", i32 2} +!8 = !{i32 2, !"Debug Info Version", i32 2} +!9 = !{!"clang version 3.5.0"} +!10 = !MDLocation(line: 3, column: 8, scope: !11) +!11 = !{!"0xb\003\003\000", !1, !4} ; [ DW_TAG_lexical_block ] +!12 = !{!12, !13, !13} +!13 = !{!"llvm.loop.vectorize.enable", i1 true} +!14 = !MDLocation(line: 4, column: 5, scope: !15) +!15 = !{!"0xb\003\0036\000", !1, !11} ; [ DW_TAG_lexical_block ] +!16 = !{!17, !17, i64 0} +!17 = !{!"int", !18, i64 0} +!18 = !{!"omnipotent char", !19, i64 0} +!19 = !{!"Simple C/C++ TBAA"} +!20 = !MDLocation(line: 6, column: 7, scope: !21) +!21 = !{!"0xb\004\0018\000", !1, !15} ; [ DW_TAG_lexical_block ] +!22 = !MDLocation(line: 7, column: 5, scope: !21) +!23 = !MDLocation(line: 9, column: 7, scope: !21) +!24 = !MDLocation(line: 14, column: 1, scope: !4) diff --git a/test/Transforms/LoopVectorize/nofloat.ll b/test/Transforms/LoopVectorize/nofloat.ll index c3c81b6f8450..e9f4c5f23e08 100644 --- a/test/Transforms/LoopVectorize/nofloat.ll +++ b/test/Transforms/LoopVectorize/nofloat.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s ; Make sure that we don't vectorize functions with 'noimplicitfloat' attributes. diff --git a/test/Transforms/LoopVectorize/non-const-n.ll b/test/Transforms/LoopVectorize/non-const-n.ll index 0c54a2b01226..b03d4f05e16f 100644 --- a/test/Transforms/LoopVectorize/non-const-n.ll +++ b/test/Transforms/LoopVectorize/non-const-n.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/nsw-crash.ll b/test/Transforms/LoopVectorize/nsw-crash.ll index e5fad14d0dda..68d993340bdb 100644 --- a/test/Transforms/LoopVectorize/nsw-crash.ll +++ b/test/Transforms/LoopVectorize/nsw-crash.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 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" diff --git a/test/Transforms/LoopVectorize/opt.ll b/test/Transforms/LoopVectorize/opt.ll index 27030a2ff2a9..a9be80fbfee6 100644 --- a/test/Transforms/LoopVectorize/opt.ll +++ b/test/Transforms/LoopVectorize/opt.ll @@ -1,5 +1,5 @@ -; RUN: opt -S -O3 -force-vector-width=2 -force-vector-unroll=1 < %s | FileCheck --check-prefix=LOOPVEC %s -; RUN: opt -S -O3 -disable-loop-vectorization -force-vector-width=2 -force-vector-unroll=1 < %s | FileCheck --check-prefix=NOLOOPVEC %s +; RUN: opt -S -O3 -force-vector-width=2 -force-vector-interleave=1 < %s | FileCheck --check-prefix=LOOPVEC %s +; RUN: opt -S -O3 -disable-loop-vectorization -force-vector-width=2 -force-vector-interleave=1 < %s | FileCheck --check-prefix=NOLOOPVEC %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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/ptr_loops.ll b/test/Transforms/LoopVectorize/ptr_loops.ll index 1259e21ebf2e..3fb38fe1ef13 100644 --- a/test/Transforms/LoopVectorize/ptr_loops.ll +++ b/test/Transforms/LoopVectorize/ptr_loops.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basicaa -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S -enable-if-conversion | FileCheck %s +; RUN: opt < %s -basicaa -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S -enable-if-conversion | 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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/read-only.ll b/test/Transforms/LoopVectorize/read-only.ll index fc8f0a5482f0..2f7a96a09d22 100644 --- a/test/Transforms/LoopVectorize/read-only.ll +++ b/test/Transforms/LoopVectorize/read-only.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/reduction.ll b/test/Transforms/LoopVectorize/reduction.ll index 791fce156220..5e6b7fa332b2 100644 --- a/test/Transforms/LoopVectorize/reduction.ll +++ b/test/Transforms/LoopVectorize/reduction.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/reverse_induction.ll b/test/Transforms/LoopVectorize/reverse_induction.ll index 65ef95dcb121..da02d01706ca 100644 --- a/test/Transforms/LoopVectorize/reverse_induction.ll +++ b/test/Transforms/LoopVectorize/reverse_induction.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=2 -force-vector-width=4 -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=2 -force-vector-width=4 -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" diff --git a/test/Transforms/LoopVectorize/reverse_iter.ll b/test/Transforms/LoopVectorize/reverse_iter.ll index f803120c4d57..13172bb17aeb 100644 --- a/test/Transforms/LoopVectorize/reverse_iter.ll +++ b/test/Transforms/LoopVectorize/reverse_iter.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/runtime-check-address-space.ll b/test/Transforms/LoopVectorize/runtime-check-address-space.ll index 848ffc428c5f..ec56f80144c4 100644 --- a/test/Transforms/LoopVectorize/runtime-check-address-space.ll +++ b/test/Transforms/LoopVectorize/runtime-check-address-space.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -march=r600 -mcpu=cayman -basicaa -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine < %s | FileCheck %s +; RUN: opt -S -march=r600 -mcpu=cayman -basicaa -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine < %s | FileCheck %s ; Check vectorization that would ordinarily require a runtime bounds ; check on the pointers when mixing address spaces. For now we cannot diff --git a/test/Transforms/LoopVectorize/runtime-check-readonly-address-space.ll b/test/Transforms/LoopVectorize/runtime-check-readonly-address-space.ll index 4e98ec504f5b..12ba3ce6c667 100644 --- a/test/Transforms/LoopVectorize/runtime-check-readonly-address-space.ll +++ b/test/Transforms/LoopVectorize/runtime-check-readonly-address-space.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -march=r600 -mcpu=cayman -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine < %s | FileCheck %s +; RUN: opt -S -march=r600 -mcpu=cayman -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine < %s | FileCheck %s ; Artificial datalayout target datalayout = "e-p:32:32:32-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024-v2048:2048:2048-n32:64" diff --git a/test/Transforms/LoopVectorize/runtime-check-readonly.ll b/test/Transforms/LoopVectorize/runtime-check-readonly.ll index 73b28301b7e7..9d02a6accd67 100644 --- a/test/Transforms/LoopVectorize/runtime-check-readonly.ll +++ b/test/Transforms/LoopVectorize/runtime-check-readonly.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/runtime-check.ll b/test/Transforms/LoopVectorize/runtime-check.ll index d15479d202b7..1edafb4ed7a9 100644 --- a/test/Transforms/LoopVectorize/runtime-check.ll +++ b/test/Transforms/LoopVectorize/runtime-check.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.9.0" diff --git a/test/Transforms/LoopVectorize/runtime-limit.ll b/test/Transforms/LoopVectorize/runtime-limit.ll index 7370a6fb93c5..324949dafd0a 100644 --- a/test/Transforms/LoopVectorize/runtime-limit.ll +++ b/test/Transforms/LoopVectorize/runtime-limit.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/safegep.ll b/test/Transforms/LoopVectorize/safegep.ll index c9508601e2c1..f853afd2bba6 100644 --- a/test/Transforms/LoopVectorize/safegep.ll +++ b/test/Transforms/LoopVectorize/safegep.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -loop-vectorize -force-vector-width=4 -force-vector-unroll=1 < %s | FileCheck %s +; RUN: opt -S -loop-vectorize -force-vector-width=4 -force-vector-interleave=1 < %s | FileCheck %s target datalayout = "e-p:32:32:32-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f16:16:16-f32:32:32-f64:32:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" diff --git a/test/Transforms/LoopVectorize/same-base-access.ll b/test/Transforms/LoopVectorize/same-base-access.ll index d623a3469096..d19458f4aa92 100644 --- a/test/Transforms/LoopVectorize/same-base-access.ll +++ b/test/Transforms/LoopVectorize/same-base-access.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S -enable-if-conversion | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S -enable-if-conversion | 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" target triple = "x86_64-apple-macosx10.9.0" diff --git a/test/Transforms/LoopVectorize/scalar-select.ll b/test/Transforms/LoopVectorize/scalar-select.ll index 257c7bebe4d5..6b37cc23ae31 100644 --- a/test/Transforms/LoopVectorize/scalar-select.ll +++ b/test/Transforms/LoopVectorize/scalar-select.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/scev-exitlim-crash.ll b/test/Transforms/LoopVectorize/scev-exitlim-crash.ll index 683621a6f69b..515477180772 100644 --- a/test/Transforms/LoopVectorize/scev-exitlim-crash.ll +++ b/test/Transforms/LoopVectorize/scev-exitlim-crash.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=2 -force-vector-width=8 -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=2 -force-vector-width=8 -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" target triple = "x86_64-apple-macosx" @@ -106,9 +106,9 @@ declare i32 @fn2(double) #1 attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } -!0 = metadata !{metadata !"int", metadata !1} -!1 = metadata !{metadata !"omnipotent char", metadata !2} -!2 = metadata !{metadata !"Simple C/C++ TBAA"} -!3 = metadata !{metadata !"double", metadata !1} -!4 = metadata !{metadata !0, metadata !0, i64 0} -!5 = metadata !{metadata !3, metadata !3, i64 0} +!0 = !{!"int", !1} +!1 = !{!"omnipotent char", !2} +!2 = !{!"Simple C/C++ TBAA"} +!3 = !{!"double", !1} +!4 = !{!0, !0, i64 0} +!5 = !{!3, !3, i64 0} diff --git a/test/Transforms/LoopVectorize/simple-unroll.ll b/test/Transforms/LoopVectorize/simple-unroll.ll index 83f35ffb609b..8bf680ac7c5f 100644 --- a/test/Transforms/LoopVectorize/simple-unroll.ll +++ b/test/Transforms/LoopVectorize/simple-unroll.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-width=4 -force-vector-unroll=2 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-width=4 -force-vector-interleave=2 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/small-loop.ll b/test/Transforms/LoopVectorize/small-loop.ll index 49ce5c539727..1d30102c3f97 100644 --- a/test/Transforms/LoopVectorize/small-loop.ll +++ b/test/Transforms/LoopVectorize/small-loop.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/start-non-zero.ll b/test/Transforms/LoopVectorize/start-non-zero.ll index 8f675afd80cb..cc474945a9d0 100644 --- a/test/Transforms/LoopVectorize/start-non-zero.ll +++ b/test/Transforms/LoopVectorize/start-non-zero.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/store-shuffle-bug.ll b/test/Transforms/LoopVectorize/store-shuffle-bug.ll index 26f4d156df61..6d3d11349b14 100644 --- a/test/Transforms/LoopVectorize/store-shuffle-bug.ll +++ b/test/Transforms/LoopVectorize/store-shuffle-bug.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -basicaa -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine < %s | FileCheck %s +; RUN: opt -S -basicaa -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/struct_access.ll b/test/Transforms/LoopVectorize/struct_access.ll index 75beae82f170..cf6f325ae306 100644 --- a/test/Transforms/LoopVectorize/struct_access.ll +++ b/test/Transforms/LoopVectorize/struct_access.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -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" target triple = "x86_64-apple-macosx10.9.0" diff --git a/test/Transforms/LoopVectorize/tbaa-nodep.ll b/test/Transforms/LoopVectorize/tbaa-nodep.ll index f31b3072bc6c..be3e74f5d68a 100644 --- a/test/Transforms/LoopVectorize/tbaa-nodep.ll +++ b/test/Transforms/LoopVectorize/tbaa-nodep.ll @@ -1,5 +1,5 @@ -; RUN: opt < %s -tbaa -basicaa -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -simplifycfg -S | FileCheck %s -; RUN: opt < %s -basicaa -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -simplifycfg -S | FileCheck %s --check-prefix=CHECK-NOTBAA +; RUN: opt < %s -tbaa -basicaa -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -simplifycfg -S | FileCheck %s +; RUN: opt < %s -basicaa -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -simplifycfg -S | FileCheck %s --check-prefix=CHECK-NOTBAA target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -93,10 +93,10 @@ for.end: ; preds = %for.body attributes #0 = { nounwind uwtable } -!0 = metadata !{metadata !1, metadata !1, i64 0} -!1 = metadata !{metadata !"float", metadata !2, i64 0} -!2 = metadata !{metadata !"omnipotent char", metadata !3, i64 0} -!3 = metadata !{metadata !"Simple C/C++ TBAA"} -!4 = metadata !{metadata !5, metadata !5, i64 0} -!5 = metadata !{metadata !"int", metadata !2, i64 0} +!0 = !{!1, !1, i64 0} +!1 = !{!"float", !2, i64 0} +!2 = !{!"omnipotent char", !3, i64 0} +!3 = !{!"Simple C/C++ TBAA"} +!4 = !{!5, !5, i64 0} +!5 = !{!"int", !2, i64 0} diff --git a/test/Transforms/LoopVectorize/undef-inst-bug.ll b/test/Transforms/LoopVectorize/undef-inst-bug.ll index ed60e801afde..0444fe894ed4 100644 --- a/test/Transforms/LoopVectorize/undef-inst-bug.ll +++ b/test/Transforms/LoopVectorize/undef-inst-bug.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -loop-vectorize -force-vector-width=4 -force-vector-unroll=1 < %s | FileCheck %s +; RUN: opt -S -loop-vectorize -force-vector-width=4 -force-vector-interleave=1 < %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" diff --git a/test/Transforms/LoopVectorize/unroll_novec.ll b/test/Transforms/LoopVectorize/unroll_novec.ll index 89f4678526de..257b4e63a915 100644 --- a/test/Transforms/LoopVectorize/unroll_novec.ll +++ b/test/Transforms/LoopVectorize/unroll_novec.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-width=1 -force-target-num-scalar-regs=16 -force-target-max-scalar-unroll=8 -force-target-instruction-cost=1 -small-loop-cost=40 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-width=1 -force-target-num-scalar-regs=16 -force-target-max-scalar-interleave=8 -force-target-instruction-cost=1 -small-loop-cost=40 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LoopVectorize/value-ptr-bug.ll b/test/Transforms/LoopVectorize/value-ptr-bug.ll index 6b06afaf0de2..7fb9095b7c10 100644 --- a/test/Transforms/LoopVectorize/value-ptr-bug.ll +++ b/test/Transforms/LoopVectorize/value-ptr-bug.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -loop-vectorize -force-vector-width=4 -force-vector-unroll=1 -dce -instcombine < %s | FileCheck %s +; RUN: opt -S -loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -dce -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" diff --git a/test/Transforms/LoopVectorize/vect.omp.persistence.ll b/test/Transforms/LoopVectorize/vect.omp.persistence.ll index f6465677839e..ea7be9c106b3 100644 --- a/test/Transforms/LoopVectorize/vect.omp.persistence.ll +++ b/test/Transforms/LoopVectorize/vect.omp.persistence.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -O2 -force-vector-unroll=2 -force-vector-width=4 -debug-only=loop-vectorize -stats -S 2>&1 | FileCheck %s +; RUN: opt < %s -O2 -force-vector-interleave=2 -force-vector-width=4 -debug-only=loop-vectorize -stats -S 2>&1 | FileCheck %s ; REQUIRES: asserts ; Loop from "rotated" @@ -61,8 +61,8 @@ for.end: ret void } -!1 = metadata !{metadata !1, metadata !2} -!2 = metadata !{metadata !"llvm.loop.vectorize.enable", i1 true} +!1 = !{!1, !2} +!2 = !{!"llvm.loop.vectorize.enable", i1 true} ; ; Test #2 @@ -84,5 +84,5 @@ return: ret i32 0 } -!3 = metadata !{metadata !3, metadata !4} -!4 = metadata !{metadata !"llvm.loop.vectorize.enable", i1 true} +!3 = !{!3, !4} +!4 = !{!"llvm.loop.vectorize.enable", i1 true} diff --git a/test/Transforms/LoopVectorize/vect.stats.ll b/test/Transforms/LoopVectorize/vect.stats.ll index 9adf2bb6cf14..c5b6e64bc9fb 100644 --- a/test/Transforms/LoopVectorize/vect.stats.ll +++ b/test/Transforms/LoopVectorize/vect.stats.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=4 -force-vector-width=4 -debug-only=loop-vectorize -stats -S 2>&1 | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=4 -force-vector-width=4 -debug-only=loop-vectorize -stats -S 2>&1 | FileCheck %s ; REQUIRES: asserts ; @@ -56,4 +56,4 @@ for.body: ; preds = %entry, %for.body for.end: ; preds = %entry, %for.body ret void -}
\ No newline at end of file +} diff --git a/test/Transforms/LoopVectorize/vectorize-once.ll b/test/Transforms/LoopVectorize/vectorize-once.ll index 97654f495018..a9b2a53f74b3 100644 --- a/test/Transforms/LoopVectorize/vectorize-once.ll +++ b/test/Transforms/LoopVectorize/vectorize-once.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S -simplifycfg | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S -simplifycfg | 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" target triple = "x86_64-apple-macosx10.8.0" @@ -68,10 +68,10 @@ _ZSt10accumulateIPiiET0_T_S2_S1_.exit: ; preds = %for.body.i, %entry attributes #0 = { nounwind readonly ssp uwtable "fp-contract-model"="standard" "no-frame-pointer-elim" "no-frame-pointer-elim-non-leaf" "realign-stack" "relocation-model"="pic" "ssp-buffers-size"="8" } -; CHECK: !0 = metadata !{metadata !0, metadata !1, metadata !2} -; CHECK: !1 = metadata !{metadata !"llvm.loop.vectorize.width", i32 1} -; CHECK: !2 = metadata !{metadata !"llvm.loop.interleave.count", i32 1} -; CHECK: !3 = metadata !{metadata !3, metadata !1, metadata !2} +; CHECK: !0 = distinct !{!0, !1, !2} +; CHECK: !1 = !{!"llvm.loop.vectorize.width", i32 1} +; CHECK: !2 = !{!"llvm.loop.interleave.count", i32 1} +; CHECK: !3 = distinct !{!3, !1, !2} -!0 = metadata !{metadata !0, metadata !1} -!1 = metadata !{metadata !"llvm.loop.vectorize.width", i32 1} +!0 = !{!0, !1} +!1 = !{!"llvm.loop.vectorize.width", i32 1} diff --git a/test/Transforms/LoopVectorize/version-mem-access.ll b/test/Transforms/LoopVectorize/version-mem-access.ll index 51d20e227ddf..7ac2fca2533f 100644 --- a/test/Transforms/LoopVectorize/version-mem-access.ll +++ b/test/Transforms/LoopVectorize/version-mem-access.ll @@ -1,4 +1,4 @@ -; RUN: opt -basicaa -loop-vectorize -enable-mem-access-versioning -force-vector-width=2 -force-vector-unroll=1 < %s -S | FileCheck %s +; RUN: opt -basicaa -loop-vectorize -enable-mem-access-versioning -force-vector-width=2 -force-vector-interleave=1 < %s -S | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" diff --git a/test/Transforms/LoopVectorize/write-only.ll b/test/Transforms/LoopVectorize/write-only.ll index 71a9cd0dc5be..2f100de82370 100644 --- a/test/Transforms/LoopVectorize/write-only.ll +++ b/test/Transforms/LoopVectorize/write-only.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -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" target triple = "x86_64-apple-macosx10.8.0" diff --git a/test/Transforms/LowerExpectIntrinsic/basic.ll b/test/Transforms/LowerExpectIntrinsic/basic.ll index e184cb05b94a..b15edc715141 100644 --- a/test/Transforms/LowerExpectIntrinsic/basic.ll +++ b/test/Transforms/LowerExpectIntrinsic/basic.ll @@ -274,7 +274,7 @@ return: ; preds = %if.end, %if.then declare i1 @llvm.expect.i1(i1, i1) nounwind readnone -; CHECK: !0 = metadata !{metadata !"branch_weights", i32 64, i32 4} -; CHECK: !1 = metadata !{metadata !"branch_weights", i32 4, i32 64} -; CHECK: !2 = metadata !{metadata !"branch_weights", i32 4, i32 64, i32 4} -; CHECK: !3 = metadata !{metadata !"branch_weights", i32 64, i32 4, i32 4} +; CHECK: !0 = !{!"branch_weights", i32 64, i32 4} +; CHECK: !1 = !{!"branch_weights", i32 4, i32 64} +; CHECK: !2 = !{!"branch_weights", i32 4, i32 64, i32 4} +; CHECK: !3 = !{!"branch_weights", i32 64, i32 4, i32 4} diff --git a/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll b/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll index ea0d515498cf..ea581d197e58 100644 --- a/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll +++ b/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -std-compile-opts -S | grep volatile | count 3 +; RUN: opt < %s -O3 -S | grep volatile | count 3 ; PR1520 ; Don't promote load volatiles/stores. This is really needed to handle setjmp/lonjmp properly. diff --git a/test/Transforms/Mem2Reg/ConvertDebugInfo.ll b/test/Transforms/Mem2Reg/ConvertDebugInfo.ll index 33eaed60fe58..a7369c0902b9 100644 --- a/test/Transforms/Mem2Reg/ConvertDebugInfo.ll +++ b/test/Transforms/Mem2Reg/ConvertDebugInfo.ll @@ -7,13 +7,13 @@ entry: %retval = alloca double ; <double*> [#uses=2] %0 = alloca double ; <double*> [#uses=2] %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] - call void @llvm.dbg.declare(metadata !{i32* %i_addr}, metadata !0), !dbg !8 -; CHECK: call void @llvm.dbg.value(metadata !{i32 %i}, i64 0, metadata ![[IVAR:[0-9]*]]) -; CHECK: call void @llvm.dbg.value(metadata !{double %j}, i64 0, metadata ![[JVAR:[0-9]*]]) + call void @llvm.dbg.declare(metadata i32* %i_addr, metadata !0, metadata !{}), !dbg !8 +; CHECK: call void @llvm.dbg.value(metadata i32 %i, i64 0, metadata ![[IVAR:[0-9]*]], metadata {{.*}}) +; CHECK: call void @llvm.dbg.value(metadata double %j, i64 0, metadata ![[JVAR:[0-9]*]], metadata {{.*}}) ; CHECK: ![[IVAR]] = {{.*}} ; [ DW_TAG_arg_variable ] [i] ; CHECK: ![[JVAR]] = {{.*}} ; [ DW_TAG_arg_variable ] [j] store i32 %i, i32* %i_addr - call void @llvm.dbg.declare(metadata !{double* %j_addr}, metadata !9), !dbg !8 + call void @llvm.dbg.declare(metadata double* %j_addr, metadata !9, metadata !{}), !dbg !8 store double %j, double* %j_addr %1 = load i32* %i_addr, align 4, !dbg !10 ; <i32> [#uses=1] %2 = add nsw i32 %1, 1, !dbg !10 ; <i32> [#uses=1] @@ -30,23 +30,23 @@ return: ; preds = %entry ret double %retval1, !dbg !10 } -declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone !llvm.dbg.cu = !{!3} !llvm.module.flags = !{!14} -!0 = metadata !{i32 786689, metadata !1, metadata !"i", metadata !2, i32 2, metadata !7, i32 0, null} ; [ DW_TAG_arg_variable ] -!1 = metadata !{i32 786478, metadata !12, metadata !2, metadata !"testfunc", metadata !"testfunc", metadata !"testfunc", i32 2, metadata !4, i1 false, i1 true, i32 0, i32 0, null, i32 0, i1 false, double (i32, double)* @testfunc, null, null, null, i32 2} ; [ DW_TAG_subprogram ] -!2 = metadata !{i32 786473, metadata !12} ; [ DW_TAG_file_type ] -!3 = metadata !{i32 786449, metadata !12, i32 1, metadata !"4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", i1 true, metadata !"", i32 0, metadata !13, metadata !13, null, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!4 = metadata !{i32 786453, metadata !12, metadata !2, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !5, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!5 = metadata !{metadata !6, metadata !7, metadata !6} -!6 = metadata !{i32 786468, metadata !12, metadata !2, metadata !"double", i32 0, i64 64, i64 64, i64 0, i32 0, i32 4} ; [ DW_TAG_base_type ] -!7 = metadata !{i32 786468, metadata !12, metadata !2, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!8 = metadata !{i32 2, i32 0, metadata !1, null} -!9 = metadata !{i32 786689, metadata !1, metadata !"j", metadata !2, i32 2, metadata !6, i32 0, null} ; [ DW_TAG_arg_variable ] -!10 = metadata !{i32 3, i32 0, metadata !11, null} -!11 = metadata !{i32 786443, metadata !12, metadata !1, i32 2, i32 0, i32 0} ; [ DW_TAG_lexical_block ] -!12 = metadata !{metadata !"testfunc.c", metadata !"/tmp"} -!13 = metadata !{i32 0} -!14 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x101\00i\002\000", !1, !2, !7} ; [ DW_TAG_arg_variable ] +!1 = !{!"0x2e\00testfunc\00testfunc\00testfunc\002\000\001\000\006\000\000\002", !12, !2, !4, null, double (i32, double)* @testfunc, null, null, null} ; [ DW_TAG_subprogram ] +!2 = !{!"0x29", !12} ; [ DW_TAG_file_type ] +!3 = !{!"0x11\001\004.2.1 (Based on Apple Inc. build 5658) (LLVM build)\001\00\000\00\000", !12, !13, !13, null, null, null} ; [ DW_TAG_compile_unit ] +!4 = !{!"0x15\00\000\000\000\000\000\000", !12, !2, null, !5, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!5 = !{!6, !7, !6} +!6 = !{!"0x24\00double\000\0064\0064\000\000\004", !12, !2} ; [ DW_TAG_base_type ] +!7 = !{!"0x24\00int\000\0032\0032\000\000\005", !12, !2} ; [ DW_TAG_base_type ] +!8 = !MDLocation(line: 2, scope: !1) +!9 = !{!"0x101\00j\002\000", !1, !2, !6} ; [ DW_TAG_arg_variable ] +!10 = !MDLocation(line: 3, scope: !11) +!11 = !{!"0xb\002\000\000", !12, !1} ; [ DW_TAG_lexical_block ] +!12 = !{!"testfunc.c", !"/tmp"} +!13 = !{i32 0} +!14 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/Mem2Reg/ConvertDebugInfo2.ll b/test/Transforms/Mem2Reg/ConvertDebugInfo2.ll index 32acdd696ecf..76d2a1aa7d2b 100644 --- a/test/Transforms/Mem2Reg/ConvertDebugInfo2.ll +++ b/test/Transforms/Mem2Reg/ConvertDebugInfo2.ll @@ -1,6 +1,6 @@ ; RUN: opt -mem2reg < %s | llvm-dis | grep ".dbg " | count 7 -declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone declare void @foo(i32, i64, i8*) @@ -11,14 +11,14 @@ entry: %z_addr.i = alloca i8* ; <i8**> [#uses=2] %a_addr = alloca i32 ; <i32*> [#uses=2] %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] - call void @llvm.dbg.declare(metadata !{i32* %a_addr}, metadata !0), !dbg !7 + call void @llvm.dbg.declare(metadata i32* %a_addr, metadata !0, metadata !{}), !dbg !7 store i32 %a, i32* %a_addr %0 = load i32* %a_addr, align 4, !dbg !8 ; <i32> [#uses=1] - call void @llvm.dbg.declare(metadata !{i32* %x_addr.i}, metadata !9) nounwind, !dbg !15 + call void @llvm.dbg.declare(metadata i32* %x_addr.i, metadata !9, metadata !{}) nounwind, !dbg !15 store i32 %0, i32* %x_addr.i - call void @llvm.dbg.declare(metadata !{i64* %y_addr.i}, metadata !16) nounwind, !dbg !15 + call void @llvm.dbg.declare(metadata i64* %y_addr.i, metadata !16, metadata !{}) nounwind, !dbg !15 store i64 55, i64* %y_addr.i - call void @llvm.dbg.declare(metadata !{i8** %z_addr.i}, metadata !17) nounwind, !dbg !15 + call void @llvm.dbg.declare(metadata i8** %z_addr.i, metadata !17, metadata !{}) nounwind, !dbg !15 store i8* bitcast (void (i32)* @baz to i8*), i8** %z_addr.i %1 = load i32* %x_addr.i, align 4, !dbg !18 ; <i32> [#uses=1] %2 = load i64* %y_addr.i, align 8, !dbg !18 ; <i64> [#uses=1] @@ -32,26 +32,26 @@ return: ; preds = %entry !llvm.dbg.cu = !{!3} !llvm.module.flags = !{!22} -!0 = metadata !{i32 786689, metadata !1, metadata !"a", metadata !2, i32 8, metadata !6, i32 0, null} ; [ DW_TAG_arg_variable ] -!1 = metadata !{i32 786478, metadata !20, metadata !2, metadata !"baz", metadata !"baz", metadata !"baz", i32 8, metadata !4, i1 false, i1 true, i32 0, i32 0, null, i32 0, i1 false, void (i32)* @baz, null, null, null, i32 8} ; [ DW_TAG_subprogram ] -!2 = metadata !{i32 786473, metadata !20} ; [ DW_TAG_file_type ] -!3 = metadata !{i32 786449, metadata !20, i32 1, metadata !"4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", i1 true, metadata !"", i32 0, metadata !21, metadata !21, null, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!4 = metadata !{i32 786453, metadata !20, metadata !2, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !5, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!5 = metadata !{null, metadata !6} -!6 = metadata !{i32 786468, metadata !20, metadata !2, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!7 = metadata !{i32 8, i32 0, metadata !1, null} -!8 = metadata !{i32 9, i32 0, metadata !1, null} -!9 = metadata !{i32 786689, metadata !10, metadata !"x", metadata !2, i32 4, metadata !6, i32 0, null} ; [ DW_TAG_arg_variable ] -!10 = metadata !{i32 786478, metadata !20, metadata !2, metadata !"bar", metadata !"bar", metadata !"bar", i32 4, metadata !11, i1 true, i1 true, i32 0, i32 0, null, i1 false, i1 false, null, null, null, null, i32 4} ; [ DW_TAG_subprogram ] -!11 = metadata !{i32 786453, metadata !20, metadata !2, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !12, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!12 = metadata !{null, metadata !6, metadata !13, metadata !14} -!13 = metadata !{i32 786468, metadata !20, metadata !2, metadata !"long int", i32 0, i64 64, i64 64, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!14 = metadata !{i32 786447, metadata !20, metadata !2, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, null} ; [ DW_TAG_pointer_type ] -!15 = metadata !{i32 4, i32 0, metadata !10, metadata !8} -!16 = metadata !{i32 786689, metadata !10, metadata !"y", metadata !2, i32 4, metadata !13, i32 0, null} ; [ DW_TAG_arg_variable ] -!17 = metadata !{i32 786689, metadata !10, metadata !"z", metadata !2, i32 4, metadata !14, i32 0, null} ; [ DW_TAG_arg_variable ] -!18 = metadata !{i32 5, i32 0, metadata !10, metadata !8} -!19 = metadata !{i32 10, i32 0, metadata !1, null} -!20 = metadata !{metadata !"bar.c", metadata !"/tmp/"} -!21 = metadata !{i32 0} -!22 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x101\00a\008\000", !1, !2, !6} ; [ DW_TAG_arg_variable ] +!1 = !{!"0x2e\00baz\00baz\00baz\008\000\001\000\006\000\000\008", !20, !2, !4, null, void (i32)* @baz, null, null, null} ; [ DW_TAG_subprogram ] +!2 = !{!"0x29", !20} ; [ DW_TAG_file_type ] +!3 = !{!"0x11\001\004.2.1 (Based on Apple Inc. build 5658) (LLVM build)\001\00\000\00\000", !20, !21, !21, null, null, null} ; [ DW_TAG_compile_unit ] +!4 = !{!"0x15\00\000\000\000\000\000\000", !20, !2, null, !5, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!5 = !{null, !6} +!6 = !{!"0x24\00int\000\0032\0032\000\000\005", !20, !2} ; [ DW_TAG_base_type ] +!7 = !MDLocation(line: 8, scope: !1) +!8 = !MDLocation(line: 9, scope: !1) +!9 = !{!"0x101\00x\004\000", !10, !2, !6} ; [ DW_TAG_arg_variable ] +!10 = !{!"0x2e\00bar\00bar\00bar\004\001\001\000\006\000\000\004", !20, !2, !11, null, null, null, null, null} ; [ DW_TAG_subprogram ] +!11 = !{!"0x15\00\000\000\000\000\000\000", !20, !2, null, !12, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!12 = !{null, !6, !13, !14} +!13 = !{!"0x24\00long int\000\0064\0064\000\000\005", !20, !2} ; [ DW_TAG_base_type ] +!14 = !{!"0xf\00\000\0064\0064\000\000", !20, !2, null} ; [ DW_TAG_pointer_type ] +!15 = !MDLocation(line: 4, scope: !10, inlinedAt: !8) +!16 = !{!"0x101\00y\004\000", !10, !2, !13} ; [ DW_TAG_arg_variable ] +!17 = !{!"0x101\00z\004\000", !10, !2, !14} ; [ DW_TAG_arg_variable ] +!18 = !MDLocation(line: 5, scope: !10, inlinedAt: !8) +!19 = !MDLocation(line: 10, scope: !1) +!20 = !{!"bar.c", !"/tmp/"} +!21 = !{i32 0} +!22 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/MemCpyOpt/callslot_deref.ll b/test/Transforms/MemCpyOpt/callslot_deref.ll new file mode 100644 index 000000000000..4d51552d0151 --- /dev/null +++ b/test/Transforms/MemCpyOpt/callslot_deref.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -S -basicaa -memcpyopt | FileCheck %s +target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) unnamed_addr nounwind +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind + +; all bytes of %dst that are touch by the memset are dereferenceable +define void @must_remove_memcpy(i8* noalias nocapture dereferenceable(4096) %dst) { +; CHECK-LABEL: @must_remove_memcpy( +; CHECK: call void @llvm.memset.p0i8.i64 +; CHECK-NOT: call void @llvm.memcpy.p0i8.p0i8.i64 + %src = alloca [4096 x i8], align 1 + %p = getelementptr inbounds [4096 x i8]* %src, i64 0, i64 0 + call void @llvm.memset.p0i8.i64(i8* %p, i8 0, i64 4096, i32 1, i1 false) + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %p, i64 4096, i32 1, i1 false) #2 + ret void +} + +; memset touch more bytes than those guaranteed to be dereferenceable +define void @must_not_remove_memcpy(i8* noalias nocapture dereferenceable(1024) %dst) { +; CHECK-LABEL: @must_not_remove_memcpy( +; CHECK: call void @llvm.memset.p0i8.i64 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 + %src = alloca [4096 x i8], align 1 + %p = getelementptr inbounds [4096 x i8]* %src, i64 0, i64 0 + call void @llvm.memset.p0i8.i64(i8* %p, i8 0, i64 4096, i32 1, i1 false) + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %p, i64 4096, i32 1, i1 false) #2 + ret void +} diff --git a/test/Transforms/MemCpyOpt/memcpy-to-memset-with-lifetimes.ll b/test/Transforms/MemCpyOpt/memcpy-to-memset-with-lifetimes.ll new file mode 100644 index 000000000000..626317614c94 --- /dev/null +++ b/test/Transforms/MemCpyOpt/memcpy-to-memset-with-lifetimes.ll @@ -0,0 +1,55 @@ +; RUN: opt -basicaa -memcpyopt -instcombine -S < %s | FileCheck %s + +target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @foo([8 x i64]* noalias nocapture sret dereferenceable(64) %sret) { +entry-block: + %a = alloca [8 x i64], align 8 + %a.cast = bitcast [8 x i64]* %a to i8* + call void @llvm.lifetime.start(i64 64, i8* %a.cast) + call void @llvm.memset.p0i8.i64(i8* %a.cast, i8 0, i64 64, i32 8, i1 false) + %sret.cast = bitcast [8 x i64]* %sret to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %sret.cast, i8* %a.cast, i64 64, i32 8, i1 false) + call void @llvm.lifetime.end(i64 64, i8* %a.cast) + ret void + +; CHECK-LABEL: @foo( +; CHECK: %[[sret_cast:[^=]+]] = bitcast [8 x i64]* %sret to i8* +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* %[[sret_cast]], i8 0, i64 64 +; CHECK-NOT: call void @llvm.memcpy +; CHECK: ret void +} + +define void @bar([8 x i64]* noalias nocapture sret dereferenceable(64) %sret, [8 x i64]* noalias nocapture dereferenceable(64) %out) { +entry-block: + %a = alloca [8 x i64], align 8 + %a.cast = bitcast [8 x i64]* %a to i8* + call void @llvm.lifetime.start(i64 64, i8* %a.cast) + call void @llvm.memset.p0i8.i64(i8* %a.cast, i8 0, i64 64, i32 8, i1 false) + %sret.cast = bitcast [8 x i64]* %sret to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %sret.cast, i8* %a.cast, i64 64, i32 8, i1 false) + call void @llvm.memset.p0i8.i64(i8* %a.cast, i8 42, i64 32, i32 8, i1 false) + %out.cast = bitcast [8 x i64]* %out to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %out.cast, i8* %a.cast, i64 64, i32 8, i1 false) + call void @llvm.lifetime.end(i64 64, i8* %a.cast) + ret void + +; CHECK-LABEL: @bar( +; CHECK: %[[a:[^=]+]] = alloca [8 x i64] +; CHECK: %[[a_cast:[^=]+]] = bitcast [8 x i64]* %[[a]] to i8* +; CHECK: call void @llvm.memset.p0i8.i64(i8* %[[a_cast]], i8 0, i64 64 +; CHECK: %[[sret_cast:[^=]+]] = bitcast [8 x i64]* %sret to i8* +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %[[sret_cast]], i8* %[[a_cast]], i64 64 +; CHECK: call void @llvm.memset.p0i8.i64(i8* %[[a_cast]], i8 42, i64 32 +; CHECK: %[[out_cast:[^=]+]] = bitcast [8 x i64]* %out to i8* +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %[[out_cast]], i8* %[[a_cast]], i64 64 +; CHECK-NOT: call void @llvm.memcpy +; CHECK: ret void +} + +declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind +declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) nounwind +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind diff --git a/test/Transforms/MergeFunc/call-and-invoke-with-ranges.ll b/test/Transforms/MergeFunc/call-and-invoke-with-ranges.ll index 9878b471500e..b2083cb5c700 100644 --- a/test/Transforms/MergeFunc/call-and-invoke-with-ranges.ll +++ b/test/Transforms/MergeFunc/call-and-invoke-with-ranges.ll @@ -87,5 +87,5 @@ lpad: declare i8 @dummy(); declare i32 @__gxx_personality_v0(...) -!0 = metadata !{i8 0, i8 2} -!1 = metadata !{i8 5, i8 7}
\ No newline at end of file +!0 = !{i8 0, i8 2} +!1 = !{i8 5, i8 7} diff --git a/test/Transforms/MergeFunc/ranges.ll b/test/Transforms/MergeFunc/ranges.ll index e25ff1d3acb1..d3e4d942a9d5 100644 --- a/test/Transforms/MergeFunc/ranges.ll +++ b/test/Transforms/MergeFunc/ranges.ll @@ -39,5 +39,5 @@ define i1 @cmp_with_same_range(i8*, i8*) { ret i1 %out } -!0 = metadata !{i8 0, i8 2} -!1 = metadata !{i8 5, i8 7} +!0 = !{i8 0, i8 2} +!1 = !{i8 5, i8 7} diff --git a/test/Transforms/MergeFunc/vector-GEP-crash.ll b/test/Transforms/MergeFunc/vector-GEP-crash.ll new file mode 100644 index 000000000000..a1eefa0bc983 --- /dev/null +++ b/test/Transforms/MergeFunc/vector-GEP-crash.ll @@ -0,0 +1,12 @@ +; RUN: opt -mergefunc -disable-output < %s +; This used to cause a crash when compairing the GEPs + +define void @foo(<2 x i64*>) { + %tmp = getelementptr <2 x i64*> %0, <2 x i64> <i64 0, i64 0> + ret void +} + +define void @bar(<2 x i64*>) { + %tmp = getelementptr <2 x i64*> %0, <2 x i64> <i64 0, i64 0> + ret void +} diff --git a/test/Transforms/MetaRenamer/metarenamer.ll b/test/Transforms/MetaRenamer/metarenamer.ll index 6297af62ff0c..4010f31ff772 100644 --- a/test/Transforms/MetaRenamer/metarenamer.ll +++ b/test/Transforms/MetaRenamer/metarenamer.ll @@ -12,7 +12,7 @@ target triple = "x86_64-pc-linux-gnu" @func_5_xxx.static_local_3_xxx = internal global i32 3, align 4 @global_3_xxx = common global i32 0, align 4 -@func_7_xxx = alias weak i32 (...)* @aliased_func_7_xxx +@func_7_xxx = weak alias i32 (...)* @aliased_func_7_xxx define i32 @aliased_func_7_xxx(...) { ret i32 0 diff --git a/test/Transforms/ObjCARC/allocas.ll b/test/Transforms/ObjCARC/allocas.ll index 7347a8fd4447..7b671df70649 100644 --- a/test/Transforms/ObjCARC/allocas.ll +++ b/test/Transforms/ObjCARC/allocas.ll @@ -23,7 +23,7 @@ declare i8* @returner2() declare void @bar(i32 ()*) declare void @use_alloca(i8**) -declare void @llvm.dbg.value(metadata, i64, metadata) +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) declare i8* @objc_msgSend(i8*, i8*, ...) @@ -495,6 +495,6 @@ arraydestroy.done1: ret void } -!0 = metadata !{} +!0 = !{} declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/ObjCARC/arc-annotations.ll b/test/Transforms/ObjCARC/arc-annotations.ll index f76ba3b80b06..c0ce44f284ca 100644 --- a/test/Transforms/ObjCARC/arc-annotations.ll +++ b/test/Transforms/ObjCARC/arc-annotations.ll @@ -73,11 +73,11 @@ return: ret void } -!0 = metadata !{} +!0 = !{} -; CHECK: ![[ANN0]] = metadata !{metadata !"(test0,%x)", metadata !"S_Use", metadata !"S_None"} -; CHECK: ![[ANN1]] = metadata !{metadata !"(test0,%x)", metadata !"S_None", metadata !"S_Retain"} -; CHECK: ![[ANN2]] = metadata !{metadata !"(test0,%x)", metadata !"S_Release", metadata !"S_Use"} -; CHECK: ![[ANN3]] = metadata !{metadata !"(test0,%x)", metadata !"S_None", metadata !"S_Release"} -; CHECK: ![[ANN4]] = metadata !{metadata !"(test0,%x)", metadata !"S_Retain", metadata !"S_None"} +; CHECK: ![[ANN0]] = !{!"(test0,%x)", !"S_Use", !"S_None"} +; CHECK: ![[ANN1]] = !{!"(test0,%x)", !"S_None", !"S_Retain"} +; CHECK: ![[ANN2]] = !{!"(test0,%x)", !"S_Release", !"S_Use"} +; CHECK: ![[ANN3]] = !{!"(test0,%x)", !"S_None", !"S_Release"} +; CHECK: ![[ANN4]] = !{!"(test0,%x)", !"S_Retain", !"S_None"} diff --git a/test/Transforms/ObjCARC/basic.ll b/test/Transforms/ObjCARC/basic.ll index 885935c51533..7bc58c42d532 100644 --- a/test/Transforms/ObjCARC/basic.ll +++ b/test/Transforms/ObjCARC/basic.ll @@ -22,7 +22,7 @@ declare void @invokee() declare i8* @returner() declare void @bar(i32 ()*) -declare void @llvm.dbg.value(metadata, i64, metadata) +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) declare i8* @objc_msgSend(i8*, i8*, ...) @@ -2679,8 +2679,8 @@ define {<2 x float>, <2 x float>} @"\01-[A z]"({}* %self, i8* nocapture %_cmd) n invoke.cont: %0 = bitcast {}* %self to i8* %1 = tail call i8* @objc_retain(i8* %0) nounwind - tail call void @llvm.dbg.value(metadata !{{}* %self}, i64 0, metadata !0) - tail call void @llvm.dbg.value(metadata !{{}* %self}, i64 0, metadata !0) + tail call void @llvm.dbg.value(metadata {}* %self, i64 0, metadata !0, metadata !{}) + tail call void @llvm.dbg.value(metadata {}* %self, i64 0, metadata !0, metadata !{}) %ivar = load i64* @"OBJC_IVAR_$_A.myZ", align 8 %add.ptr = getelementptr i8* %0, i64 %ivar %tmp1 = bitcast i8* %add.ptr to float* @@ -3011,9 +3011,9 @@ define void @test67(i8* %x) { !llvm.module.flags = !{!1} -!0 = metadata !{} -!1 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{} +!1 = !{i32 1, !"Debug Info Version", i32 2} ; CHECK: attributes #0 = { nounwind readnone } ; CHECK: attributes [[NUW]] = { nounwind } -; CHECK: ![[RELEASE]] = metadata !{} +; CHECK: ![[RELEASE]] = !{} diff --git a/test/Transforms/ObjCARC/cfg-hazards.ll b/test/Transforms/ObjCARC/cfg-hazards.ll index 61e5a3b1dccb..746d56df8fad 100644 --- a/test/Transforms/ObjCARC/cfg-hazards.ll +++ b/test/Transforms/ObjCARC/cfg-hazards.ll @@ -432,4 +432,4 @@ exit: ; CHECK: attributes [[NUW]] = { nounwind } -!0 = metadata !{} +!0 = !{} diff --git a/test/Transforms/ObjCARC/contract-marker.ll b/test/Transforms/ObjCARC/contract-marker.ll index 55a1b28e1c46..a8282607cb3b 100644 --- a/test/Transforms/ObjCARC/contract-marker.ll +++ b/test/Transforms/ObjCARC/contract-marker.ll @@ -22,6 +22,6 @@ declare void @bar(i8*) !clang.arc.retainAutoreleasedReturnValueMarker = !{!0} -!0 = metadata !{metadata !"mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue"} +!0 = !{!"mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue"} ; CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/Transforms/ObjCARC/contract-storestrong.ll b/test/Transforms/ObjCARC/contract-storestrong.ll index 50a2d9756648..f9308c8fdee2 100644 --- a/test/Transforms/ObjCARC/contract-storestrong.ll +++ b/test/Transforms/ObjCARC/contract-storestrong.ll @@ -169,6 +169,6 @@ entry: ret void } -!0 = metadata !{} +!0 = !{} ; CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/Transforms/ObjCARC/contract-testcases.ll b/test/Transforms/ObjCARC/contract-testcases.ll index 0bf63a6e5174..74a4a7f989cb 100644 --- a/test/Transforms/ObjCARC/contract-testcases.ll +++ b/test/Transforms/ObjCARC/contract-testcases.ll @@ -89,7 +89,7 @@ lpad: ; preds = %entry !clang.arc.retainAutoreleasedReturnValueMarker = !{!0} -!0 = metadata !{metadata !"mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue"} +!0 = !{!"mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue"} ; CHECK: attributes #0 = { optsize } ; CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/Transforms/ObjCARC/empty-block.ll b/test/Transforms/ObjCARC/empty-block.ll index 0440ab8f7c07..cc82d1088110 100644 --- a/test/Transforms/ObjCARC/empty-block.ll +++ b/test/Transforms/ObjCARC/empty-block.ll @@ -56,4 +56,4 @@ define %0* @test1() nounwind { declare %0* @foo() -!0 = metadata !{} +!0 = !{} diff --git a/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll b/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll index 79e300cb6b43..c72566cd2065 100644 --- a/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll +++ b/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll @@ -41,10 +41,10 @@ entry: %tmp2 = bitcast %struct._class_t* %tmp to i8*, !dbg !37 ; CHECK: call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %tmp2, i8* %tmp1) %call = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %tmp2, i8* %tmp1), !dbg !37, !clang.arc.no_objc_arc_exceptions !38 - call void @llvm.dbg.value(metadata !{i8* %call}, i64 0, metadata !12), !dbg !37 + call void @llvm.dbg.value(metadata i8* %call, i64 0, metadata i32 02, metadata !{}), !dbg !37 ; CHECK: call i8* @objc_retain(i8* %call) [[NUW:#[0-9]+]] %tmp3 = call i8* @objc_retain(i8* %call) nounwind, !dbg !39 - call void @llvm.dbg.value(metadata !{i8* %call}, i64 0, metadata !25), !dbg !39 + call void @llvm.dbg.value(metadata i8* %call, i64 0, metadata !25, metadata !{}), !dbg !39 invoke fastcc void @ThrowFunc(i8* %call) to label %eh.cont unwind label %lpad, !dbg !40, !clang.arc.no_objc_arc_exceptions !38 @@ -58,7 +58,7 @@ lpad: ; preds = %entry catch i8* null, !dbg !40 %tmp5 = extractvalue { i8*, i32 } %tmp4, 0, !dbg !40 %exn.adjusted = call i8* @objc_begin_catch(i8* %tmp5) nounwind, !dbg !44 - call void @llvm.dbg.value(metadata !45, i64 0, metadata !21), !dbg !46 + call void @llvm.dbg.value(metadata i8 0, i64 0, metadata !21, metadata !{}), !dbg !46 call void @objc_end_catch(), !dbg !49, !clang.arc.no_objc_arc_exceptions !38 ; CHECK: call void @objc_release(i8* %call) call void @objc_release(i8* %call) nounwind, !dbg !42, !clang.imprecise_release !38 @@ -72,7 +72,7 @@ if.end: ; preds = %lpad, %eh.cont ret i32 0, !dbg !54 } -declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind @@ -87,7 +87,7 @@ declare void @objc_exception_rethrow() define internal fastcc void @ThrowFunc(i8* %obj) uwtable noinline ssp { entry: %tmp = call i8* @objc_retain(i8* %obj) nounwind - call void @llvm.dbg.value(metadata !{i8* %obj}, i64 0, metadata !32), !dbg !55 + call void @llvm.dbg.value(metadata i8* %obj, i64 0, metadata !32, metadata !{}), !dbg !55 %tmp1 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_1", align 8, !dbg !56 %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_5", align 8, !dbg !56, !invariant.load !38 %tmp3 = bitcast %struct._class_t* %tmp1 to i8*, !dbg !56 @@ -102,7 +102,7 @@ declare void @objc_release(i8*) nonlazybind declare void @NSLog(i8*, ...) -declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone ; CHECK: attributes #0 = { ssp uwtable } ; CHECK: attributes #1 = { nounwind readnone } @@ -113,62 +113,62 @@ declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!33, !34, !35, !36, !61} -!0 = metadata !{i32 786449, metadata !60, i32 16, metadata !"clang version 3.3 ", i1 true, metadata !"", i32 2, metadata !1, metadata !1, metadata !3, metadata !1, null, metadata !""} ; [ DW_TAG_compile_unit ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] [DW_LANG_ObjC] -!1 = metadata !{i32 0} -!3 = metadata !{metadata !5, metadata !27} -!5 = metadata !{i32 786478, metadata !60, metadata !6, metadata !"main", metadata !"main", metadata !"", i32 9, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 0, i1 true, i32 ()* @main, null, null, metadata !10, i32 10} ; [ DW_TAG_subprogram ] [line 9] [def] [scope 10] [main] -!6 = metadata !{i32 786473, metadata !60} ; [ DW_TAG_file_type ] -!7 = metadata !{i32 786453, i32 0, null, i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!8 = metadata !{metadata !9} -!9 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] -!10 = metadata !{metadata !11} -!11 = metadata !{metadata !12, metadata !21, metadata !25} -!12 = metadata !{i32 786688, metadata !13, metadata !"obj", metadata !6, i32 11, metadata !14, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [obj] [line 11] -!13 = metadata !{i32 786443, metadata !60, metadata !5, i32 10, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] -!14 = metadata !{i32 786454, metadata !60, null, metadata !"id", i32 11, i64 0, i64 0, i64 0, i32 0, metadata !15} ; [ DW_TAG_typedef ] [id] [line 11, size 0, align 0, offset 0] [from ] -!15 = metadata !{i32 786447, metadata !60, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !16} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from objc_object] -!16 = metadata !{i32 786451, metadata !60, null, metadata !"objc_object", i32 0, i64 0, i64 0, i32 0, i32 0, null, metadata !17, i32 0, null, i32 0, null} ; [ DW_TAG_structure_type ] [objc_object] [line 0, size 0, align 0, offset 0] [def] [from ] -!17 = metadata !{metadata !18} -!18 = metadata !{i32 786445, metadata !60, metadata !16, metadata !"isa", i32 0, i64 64, i64 0, i64 0, i32 0, metadata !19} ; [ DW_TAG_member ] [isa] [line 0, size 64, align 0, offset 0] [from ] -!19 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 0, i64 0, i32 0, metadata !20} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 0, offset 0] [from objc_class] -!20 = metadata !{i32 786451, metadata !60, null, metadata !"objc_class", i32 0, i64 0, i64 0, i32 0, i32 4, null, null, i32 0, null, null, null} ; [ DW_TAG_structure_type ] [objc_class] [line 0, size 0, align 0, offset 0] [decl] [from ] -!21 = metadata !{i32 786688, metadata !22, metadata !"ok", metadata !6, i32 13, metadata !23, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [ok] [line 13] -!22 = metadata !{i32 786443, metadata !60, metadata !13, i32 12, i32 0, i32 1} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] -!23 = metadata !{i32 786454, metadata !60, null, metadata !"BOOL", i32 62, i64 0, i64 0, i64 0, i32 0, metadata !24} ; [ DW_TAG_typedef ] [BOOL] [line 62, size 0, align 0, offset 0] [from signed char] -!24 = metadata !{i32 786468, null, null, metadata !"signed char", i32 0, i64 8, i64 8, i64 0, i32 0, i32 6} ; [ DW_TAG_base_type ] [signed char] [line 0, size 8, align 8, offset 0, enc DW_ATE_signed_char] -!25 = metadata !{i32 786688, metadata !26, metadata !"obj2", metadata !6, i32 15, metadata !14, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [obj2] [line 15] -!26 = metadata !{i32 786443, metadata !60, metadata !22, i32 14, i32 0, i32 2} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] -!27 = metadata !{i32 786478, metadata !60, metadata !6, metadata !"ThrowFunc", metadata !"ThrowFunc", metadata !"", i32 4, metadata !28, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (i8*)* @ThrowFunc, null, null, metadata !30, i32 5} ; [ DW_TAG_subprogram ] [line 4] [local] [def] [scope 5] [ThrowFunc] -!28 = metadata !{i32 786453, i32 0, null, i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !29, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!29 = metadata !{null, metadata !14} -!30 = metadata !{metadata !31} -!31 = metadata !{metadata !32} -!32 = metadata !{i32 786689, metadata !27, metadata !"obj", metadata !6, i32 16777220, metadata !14, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [obj] [line 4] -!33 = metadata !{i32 1, metadata !"Objective-C Version", i32 2} -!34 = metadata !{i32 1, metadata !"Objective-C Image Info Version", i32 0} -!35 = metadata !{i32 1, metadata !"Objective-C Image Info Section", metadata !"__DATA, __objc_imageinfo, regular, no_dead_strip"} -!36 = metadata !{i32 4, metadata !"Objective-C Garbage Collection", i32 0} -!37 = metadata !{i32 11, i32 0, metadata !13, null} -!38 = metadata !{} -!39 = metadata !{i32 15, i32 0, metadata !26, null} -!40 = metadata !{i32 17, i32 0, metadata !41, null} -!41 = metadata !{i32 786443, metadata !60, metadata !26, i32 16, i32 0, i32 3} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] -!42 = metadata !{i32 22, i32 0, metadata !26, null} -!43 = metadata !{i32 23, i32 0, metadata !22, null} -!44 = metadata !{i32 19, i32 0, metadata !41, null} -!45 = metadata !{i8 0} -!46 = metadata !{i32 20, i32 0, metadata !47, null} -!47 = metadata !{i32 786443, metadata !60, metadata !48, i32 19, i32 0, i32 5} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] -!48 = metadata !{i32 786443, metadata !60, metadata !26, i32 19, i32 0, i32 4} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] -!49 = metadata !{i32 21, i32 0, metadata !47, null} -!50 = metadata !{i32 24, i32 0, metadata !51, null} -!51 = metadata !{i32 786443, metadata !60, metadata !22, i32 23, i32 0, i32 6} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] -!52 = metadata !{i32 25, i32 0, metadata !51, null} -!53 = metadata !{i32 27, i32 0, metadata !13, null} -!54 = metadata !{i32 28, i32 0, metadata !13, null} -!55 = metadata !{i32 4, i32 0, metadata !27, null} -!56 = metadata !{i32 6, i32 0, metadata !57, null} -!57 = metadata !{i32 786443, metadata !60, metadata !27, i32 5, i32 0, i32 7} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] -!58 = metadata !{i32 7, i32 0, metadata !57, null} -!60 = metadata !{metadata !"test.m", metadata !"/Volumes/Files/gottesmmcab/Radar/12906997"} -!61 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x11\0016\00clang version 3.3 \001\00\002\00\000", !60, !1, !1, !3, !1, null} ; [ DW_TAG_compile_unit ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] [DW_LANG_ObjC] +!1 = !{i32 0} +!3 = !{!5, !27} +!5 = !{!"0x2e\00main\00main\00\009\000\001\000\006\000\001\0010", !60, !6, !7, null, i32 ()* @main, null, null, !10} ; [ DW_TAG_subprogram ] [line 9] [def] [scope 10] [main] +!6 = !{!"0x29", !60} ; [ DW_TAG_file_type ] +!7 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !8, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!8 = !{!9} +!9 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!10 = !{!11} +!11 = !{!12, !21, !25} +!12 = !{!"0x100\00obj\0011\000", !13, !6, !14} ; [ DW_TAG_auto_variable ] [obj] [line 11] +!13 = !{!"0xb\0010\000\000", !60, !5} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] +!14 = !{!"0x16\00id\0011\000\000\000\000", !60, null, !15} ; [ DW_TAG_typedef ] [id] [line 11, size 0, align 0, offset 0] [from ] +!15 = !{!"0xf\00\000\0064\0064\000\000", !60, null, !16} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from objc_object] +!16 = !{!"0x13\00objc_object\000\000\000\000\000\000", !60, null, null, !17, null, i32 0, null} ; [ DW_TAG_structure_type ] [objc_object] [line 0, size 0, align 0, offset 0] [def] [from ] +!17 = !{!18} +!18 = !{!"0xd\00isa\000\0064\000\000\000", !60, !16, !19} ; [ DW_TAG_member ] [isa] [line 0, size 64, align 0, offset 0] [from ] +!19 = !{!"0xf\00\000\0064\000\000\000", null, null, !20} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 0, offset 0] [from objc_class] +!20 = !{!"0x13\00objc_class\000\000\000\000\004\000", !60, null, null, null, null, null, null} ; [ DW_TAG_structure_type ] [objc_class] [line 0, size 0, align 0, offset 0] [decl] [from ] +!21 = !{!"0x100\00ok\0013\000", !22, !6, !23} ; [ DW_TAG_auto_variable ] [ok] [line 13] +!22 = !{!"0xb\0012\000\001", !60, !13} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] +!23 = !{!"0x16\00BOOL\0062\000\000\000\000", !60, null, !24} ; [ DW_TAG_typedef ] [BOOL] [line 62, size 0, align 0, offset 0] [from signed char] +!24 = !{!"0x24\00signed char\000\008\008\000\000\006", null, null} ; [ DW_TAG_base_type ] [signed char] [line 0, size 8, align 8, offset 0, enc DW_ATE_signed_char] +!25 = !{!"0x100\00obj2\0015\000", !26, !6, !14} ; [ DW_TAG_auto_variable ] [obj2] [line 15] +!26 = !{!"0xb\0014\000\002", !60, !22} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] +!27 = !{!"0x2e\00ThrowFunc\00ThrowFunc\00\004\001\001\000\006\00256\001\005", !60, !6, !28, null, void (i8*)* @ThrowFunc, null, null, !30} ; [ DW_TAG_subprogram ] [line 4] [local] [def] [scope 5] [ThrowFunc] +!28 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !29, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!29 = !{null, !14} +!30 = !{!31} +!31 = !{!32} +!32 = !{!"0x101\00obj\0016777220\000", !27, !6, !14} ; [ DW_TAG_arg_variable ] [obj] [line 4] +!33 = !{i32 1, !"Objective-C Version", i32 2} +!34 = !{i32 1, !"Objective-C Image Info Version", i32 0} +!35 = !{i32 1, !"Objective-C Image Info Section", !"__DATA, __objc_imageinfo, regular, no_dead_strip"} +!36 = !{i32 4, !"Objective-C Garbage Collection", i32 0} +!37 = !MDLocation(line: 11, scope: !13) +!38 = !{} +!39 = !MDLocation(line: 15, scope: !26) +!40 = !MDLocation(line: 17, scope: !41) +!41 = !{!"0xb\0016\000\003", !60, !26} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] +!42 = !MDLocation(line: 22, scope: !26) +!43 = !MDLocation(line: 23, scope: !22) +!44 = !MDLocation(line: 19, scope: !41) +!45 = !{i8 0} +!46 = !MDLocation(line: 20, scope: !47) +!47 = !{!"0xb\0019\000\005", !60, !48} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] +!48 = !{!"0xb\0019\000\004", !60, !26} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] +!49 = !MDLocation(line: 21, scope: !47) +!50 = !MDLocation(line: 24, scope: !51) +!51 = !{!"0xb\0023\000\006", !60, !22} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] +!52 = !MDLocation(line: 25, scope: !51) +!53 = !MDLocation(line: 27, scope: !13) +!54 = !MDLocation(line: 28, scope: !13) +!55 = !MDLocation(line: 4, scope: !27) +!56 = !MDLocation(line: 6, scope: !57) +!57 = !{!"0xb\005\000\007", !60, !27} ; [ DW_TAG_lexical_block ] [/Volumes/Files/gottesmmcab/Radar/12906997/test.m] +!58 = !MDLocation(line: 7, scope: !57) +!60 = !{!"test.m", !"/Volumes/Files/gottesmmcab/Radar/12906997"} +!61 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/ObjCARC/escape.ll b/test/Transforms/ObjCARC/escape.ll index 28f2e807798a..357f7592d83c 100644 --- a/test/Transforms/ObjCARC/escape.ll +++ b/test/Transforms/ObjCARC/escape.ll @@ -128,7 +128,7 @@ declare i8* @objc_storeWeak(i8**, i8*) declare i8* @not_really_objc_storeWeak(i8**, i8*) declare void @objc_release(i8*) -!0 = metadata !{} +!0 = !{} ; CHECK: attributes [[NUW]] = { nounwind } ; CHECK: attributes #1 = { nounwind ssp } diff --git a/test/Transforms/ObjCARC/intrinsic-use.ll b/test/Transforms/ObjCARC/intrinsic-use.ll index f3833cb54297..b1e56c8e9de1 100644 --- a/test/Transforms/ObjCARC/intrinsic-use.ll +++ b/test/Transforms/ObjCARC/intrinsic-use.ll @@ -112,5 +112,5 @@ entry: } -!0 = metadata !{} +!0 = !{} diff --git a/test/Transforms/ObjCARC/invoke.ll b/test/Transforms/ObjCARC/invoke.ll index 04d057b9d496..5ef5184154b7 100644 --- a/test/Transforms/ObjCARC/invoke.ll +++ b/test/Transforms/ObjCARC/invoke.ll @@ -221,4 +221,4 @@ declare i32 @__objc_personality_v0(...) ; CHECK: attributes [[NUW]] = { nounwind } -!0 = metadata !{} +!0 = !{} diff --git a/test/Transforms/ObjCARC/nested.ll b/test/Transforms/ObjCARC/nested.ll index 2eeb4fc25873..7d72e37f8034 100644 --- a/test/Transforms/ObjCARC/nested.ll +++ b/test/Transforms/ObjCARC/nested.ll @@ -21,7 +21,7 @@ declare void @__crasher_block_invoke(i8* nocapture) declare i8* @objc_retainBlock(i8*) declare void @__crasher_block_invoke1(i8* nocapture) -!0 = metadata !{} +!0 = !{} ; Delete a nested retain+release pair. diff --git a/test/Transforms/ObjCARC/path-overflow.ll b/test/Transforms/ObjCARC/path-overflow.ll index 3c14353947ae..d23965310127 100644 --- a/test/Transforms/ObjCARC/path-overflow.ll +++ b/test/Transforms/ObjCARC/path-overflow.ll @@ -2190,4 +2190,4 @@ return: ; No predecessors! } -!0 = metadata !{} +!0 = !{} diff --git a/test/Transforms/ObjCARC/provenance.ll b/test/Transforms/ObjCARC/provenance.ll new file mode 100644 index 000000000000..937c68924357 --- /dev/null +++ b/test/Transforms/ObjCARC/provenance.ll @@ -0,0 +1,52 @@ +; RUN: opt -disable-output -pa-eval %s 2>&1 | FileCheck %s + +@"\01l_objc_msgSend_fixup_" = global i8 0 +@g1 = global i8 0, section "__OBJC,__message_refs,literal_pointers,no_dead_strip" +@g2 = global i8 0, section "__DATA, __objc_classrefs, regular, no_dead_strip" +@g3 = global i8 0, section "__DATA, __objc_superrefs, regular, no_dead_strip" +@g4 = global i8 0, section "__TEXT,__objc_methname,cstring_literals" +@g5 = global i8 0, section "__TEXT,__cstring,cstring_literals" + +declare void @g(i8) + +define void @f(i8* %a, i8** %b, i8** %c) { + %y1 = load i8* %a + call void @g(i8 %y1) + + %y2 = load i8** %b + %y3 = load i8** %c + + %x0 = load i8* @"\01l_objc_msgSend_fixup_" + call void @g(i8 %x0) + + %x1 = load i8* @g1 + call void @g(i8 %x1) + + %x2 = load i8* @g2 + call void @g(i8 %x2) + + %x3 = load i8* @g3 + call void @g(i8 %x3) + + %x4 = load i8* @g4 + call void @g(i8 %x4) + + %x5 = load i8* @g5 + call void @g(i8 %x5) + ret void +} + +; CHECK: y1 and y2 are related. +; CHECK: y1 and y3 are related. +; CHECK: y2 and y3 are related. +; CHECK: x0 and y1 are not related. +; CHECK: x0 and y2 are not related. +; CHECK: x0 and y3 are not related. +; CHECK: l_objc_msgSend_fixup_ and y1 are not related. +; CHECK: l_objc_msgSend_fixup_ and y2 are not related. +; CHECK: l_objc_msgSend_fixup_ and y3 are not related. +; CHECK: x1 and y1 are not related. +; CHECK: x2 and y1 are not related. +; CHECK: x3 and y1 are not related. +; CHECK: x4 and y1 are not related. +; CHECK: x5 and y1 are not related. diff --git a/test/Transforms/ObjCARC/retain-not-declared.ll b/test/Transforms/ObjCARC/retain-not-declared.ll index 3a2bd03692e1..416202222aa8 100644 --- a/test/Transforms/ObjCARC/retain-not-declared.ll +++ b/test/Transforms/ObjCARC/retain-not-declared.ll @@ -64,6 +64,6 @@ lpad100: ; preds = %invoke.cont93 declare i32 @__gxx_personality_v0(...) -!0 = metadata !{} +!0 = !{} ; CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/Transforms/ObjCARC/split-backedge.ll b/test/Transforms/ObjCARC/split-backedge.ll index 1b7cf441a685..2507173f4b7e 100644 --- a/test/Transforms/ObjCARC/split-backedge.ll +++ b/test/Transforms/ObjCARC/split-backedge.ll @@ -45,6 +45,6 @@ declare void @objc_release(i8*) declare i8* @objc_retain(i8*) declare void @use_pointer(i8*) -!0 = metadata !{} +!0 = !{} ; CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/Transforms/ObjCARC/weak-copies.ll b/test/Transforms/ObjCARC/weak-copies.ll index 5dab4e049e22..13d0b0a0c6b7 100644 --- a/test/Transforms/ObjCARC/weak-copies.ll +++ b/test/Transforms/ObjCARC/weak-copies.ll @@ -86,4 +86,4 @@ declare void @objc_destroyWeak(i8**) ; CHECK: attributes [[NUW]] = { nounwind } -!0 = metadata !{} +!0 = !{} diff --git a/test/Transforms/PartiallyInlineLibCalls/bad-prototype.ll b/test/Transforms/PartiallyInlineLibCalls/bad-prototype.ll new file mode 100644 index 000000000000..34cd672ed267 --- /dev/null +++ b/test/Transforms/PartiallyInlineLibCalls/bad-prototype.ll @@ -0,0 +1,13 @@ +; RUN: opt -S -partially-inline-libcalls < %s | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" + +declare i32 @sqrt() + +; CHECK-LABEL: @foo +define i32 @foo() { + ; CHECK: call{{.*}}@sqrt + ; CHECK-NOT: call{{.*}}@sqrt + %r = call i32 @sqrt() + ret i32 %r +} diff --git a/test/Transforms/Reassociate/2006-04-27-ReassociateVector.ll b/test/Transforms/Reassociate/2006-04-27-ReassociateVector.ll index f78395540026..ea869842b180 100644 --- a/test/Transforms/Reassociate/2006-04-27-ReassociateVector.ll +++ b/test/Transforms/Reassociate/2006-04-27-ReassociateVector.ll @@ -3,7 +3,7 @@ define <4 x float> @test1() { ; CHECK-LABEL: test1 ; CHECK-NEXT: %tmp1 = fsub <4 x float> zeroinitializer, zeroinitializer -; CHECK-NEXT: %tmp2 = fmul <4 x float> zeroinitializer, %tmp1 +; CHECK-NEXT: %tmp2 = fmul <4 x float> %tmp1, zeroinitializer ; CHECK-NEXT: ret <4 x float> %tmp2 %tmp1 = fsub <4 x float> zeroinitializer, zeroinitializer diff --git a/test/Transforms/Reassociate/basictest.ll b/test/Transforms/Reassociate/basictest.ll index d70bfcbb72c6..0194ce2e302c 100644 --- a/test/Transforms/Reassociate/basictest.ll +++ b/test/Transforms/Reassociate/basictest.ll @@ -203,7 +203,7 @@ define i32 @test14(i32 %X1, i32 %X2) { ; CHECK-LABEL: @test14 ; CHECK-NEXT: sub i32 %X1, %X2 -; CHECK-NEXT: mul i32 %tmp, 47 +; CHECK-NEXT: mul i32 %B2, 47 ; CHECK-NEXT: ret i32 } diff --git a/test/Transforms/Reassociate/canonicalize-neg-const.ll b/test/Transforms/Reassociate/canonicalize-neg-const.ll new file mode 100644 index 000000000000..e85a963f6dda --- /dev/null +++ b/test/Transforms/Reassociate/canonicalize-neg-const.ll @@ -0,0 +1,158 @@ +; RUN: opt -reassociate -gvn -S < %s | FileCheck %s + +; (x + 0.1234 * y) * (x + -0.1234 * y) -> (x + 0.1234 * y) * (x - 0.1234 * y) +define double @test1(double %x, double %y) { +; CHECK-LABEL: @test1 +; CHECK-NEXT: fmul double %y, 1.234000e-01 +; CHECK-NEXT: fadd double %x, %mul +; CHECK-NEXT: fsub double %x, %mul +; CHECK-NEXT: fmul double %add{{.*}}, %add{{.*}} +; CHECK-NEXT: ret double %mul + + %mul = fmul double 1.234000e-01, %y + %add = fadd double %mul, %x + %mul1 = fmul double -1.234000e-01, %y + %add2 = fadd double %mul1, %x + %mul3 = fmul double %add, %add2 + ret double %mul3 +} + +; (x + -0.1234 * y) * (x + -0.1234 * y) -> (x - 0.1234 * y) * (x - 0.1234 * y) +define double @test2(double %x, double %y) { +; CHECK-LABEL: @test2 +; CHECK-NEXT: fmul double %y, 1.234000e-01 +; CHECK-NEXT: fsub double %x, %mul +; CHECK-NEXT: fmul double %add{{.*}}, %add{{.*}} +; CHECK-NEXT: ret double %mul + + %mul = fmul double %y, -1.234000e-01 + %add = fadd double %mul, %x + %mul1 = fmul double %y, -1.234000e-01 + %add2 = fadd double %mul1, %x + %mul3 = fmul double %add, %add2 + ret double %mul3 +} + +; (x + 0.1234 * y) * (x - -0.1234 * y) -> (x + 0.1234 * y) * (x + 0.1234 * y) +define double @test3(double %x, double %y) { +; CHECK-LABEL: @test3 +; CHECK-NEXT: fmul double %y, 1.234000e-01 +; CHECK-NEXT: fadd double %x, %mul +; CHECK-NEXT: fmul double %add{{.*}}, %add{{.*}} +; CHECK-NEXT: ret double + + %mul = fmul double %y, 1.234000e-01 + %add = fadd double %mul, %x + %mul1 = fmul double %y, -1.234000e-01 + %add2 = fsub double %x, %mul1 + %mul3 = fmul double %add, %add2 + ret double %mul3 +} + +; Canonicalize (x - -1234 * y) +define i64 @test4(i64 %x, i64 %y) { +; CHECK-LABEL: @test4 +; CHECK-NEXT: mul i64 %y, 1234 +; CHECK-NEXT: add i64 %mul, %x +; CHECK-NEXT: ret i64 %sub + + %mul = mul i64 %y, -1234 + %sub = sub i64 %x, %mul + ret i64 %sub +} + +; Canonicalize (x - -0.1234 * y) +define double @test5(double %x, double %y) { +; CHECK-LABEL: @test5 +; CHECK-NEXT: fmul double %y, 1.234000e-01 +; CHECK-NEXT: fadd double %x, %mul +; CHECK-NEXT: ret double + + %mul = fmul double -1.234000e-01, %y + %sub = fsub double %x, %mul + ret double %sub +} + +; Don't modify (-0.1234 * y - x) +define double @test6(double %x, double %y) { +; CHECK-LABEL: @test6 +; CHECK-NEXT: fmul double %y, -1.234000e-01 +; CHECK-NEXT: fsub double %mul, %x +; CHECK-NEXT: ret double %sub + + %mul = fmul double -1.234000e-01, %y + %sub = fsub double %mul, %x + ret double %sub +} + +; Canonicalize (-0.1234 * y + x) -> (x - 0.1234 * y) +define double @test7(double %x, double %y) { +; CHECK-LABEL: @test7 +; CHECK-NEXT: fmul double %y, 1.234000e-01 +; CHECK-NEXT: fsub double %x, %mul +; CHECK-NEXT: ret double %add + + %mul = fmul double -1.234000e-01, %y + %add = fadd double %mul, %x + ret double %add +} + +; Canonicalize (y * -0.1234 + x) -> (x - 0.1234 * y) +define double @test8(double %x, double %y) { +; CHECK-LABEL: @test8 +; CHECK-NEXT: fmul double %y, 1.234000e-01 +; CHECK-NEXT: fsub double %x, %mul +; CHECK-NEXT: ret double %add + + %mul = fmul double %y, -1.234000e-01 + %add = fadd double %mul, %x + ret double %add +} + +; Canonicalize (x - -0.1234 / y) +define double @test9(double %x, double %y) { +; CHECK-LABEL: @test9 +; CHECK-NEXT: fdiv double 1.234000e-01, %y +; CHECK-NEXT: fadd double %x, %div +; CHECK-NEXT: ret double + + %div = fdiv double -1.234000e-01, %y + %sub = fsub double %x, %div + ret double %sub +} + +; Don't modify (-0.1234 / y - x) +define double @test10(double %x, double %y) { +; CHECK-LABEL: @test10 +; CHECK-NEXT: fdiv double -1.234000e-01, %y +; CHECK-NEXT: fsub double %div, %x +; CHECK-NEXT: ret double %sub + + %div = fdiv double -1.234000e-01, %y + %sub = fsub double %div, %x + ret double %sub +} + +; Canonicalize (-0.1234 / y + x) -> (x - 0.1234 / y) +define double @test11(double %x, double %y) { +; CHECK-LABEL: @test11 +; CHECK-NEXT: fdiv double 1.234000e-01, %y +; CHECK-NEXT: fsub double %x, %div +; CHECK-NEXT: ret double %add + + %div = fdiv double -1.234000e-01, %y + %add = fadd double %div, %x + ret double %add +} + +; Canonicalize (y / -0.1234 + x) -> (x - y / 0.1234) +define double @test12(double %x, double %y) { +; CHECK-LABEL: @test12 +; CHECK-NEXT: fdiv double %y, 1.234000e-01 +; CHECK-NEXT: fsub double %x, %div +; CHECK-NEXT: ret double %add + + %div = fdiv double %y, -1.234000e-01 + %add = fadd double %div, %x + ret double %add +} diff --git a/test/Transforms/Reassociate/commute.ll b/test/Transforms/Reassociate/commute.ll new file mode 100644 index 000000000000..760e51b05e1c --- /dev/null +++ b/test/Transforms/Reassociate/commute.ll @@ -0,0 +1,19 @@ +; RUN: opt -reassociate -S < %s | FileCheck %s + +declare void @use(i32) + +define void @test1(i32 %x, i32 %y) { +; CHECK-LABEL: test1 +; CHECK: mul i32 %y, %x +; CHECK: mul i32 %y, %x +; CHECK: sub i32 %1, %2 +; CHECK: call void @use(i32 %{{.*}}) +; CHECK: call void @use(i32 %{{.*}}) + + %1 = mul i32 %x, %y + %2 = mul i32 %y, %x + %3 = sub i32 %1, %2 + call void @use(i32 %1) + call void @use(i32 %3) + ret void +} diff --git a/test/Transforms/Reassociate/fast-AgressiveSubMove.ll b/test/Transforms/Reassociate/fast-AgressiveSubMove.ll new file mode 100644 index 000000000000..0c28ed164910 --- /dev/null +++ b/test/Transforms/Reassociate/fast-AgressiveSubMove.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -reassociate -S | FileCheck %s + +define float @test1(float %A) { +; CHECK-LABEL: test1 +; CHECK-NEXT: %X = fadd float %A, 1.000000e+00 +; CHECK-NEXT: %Y = fadd float %A, 1.000000e+00 +; CHECK-NEXT: %r = fsub float %X, %Y +; CHECK-NEXT: ret float %r + + %X = fadd float %A, 1.000000e+00 + %Y = fadd float %A, 1.000000e+00 + %r = fsub float %X, %Y + ret float %r +} + +define float @test2(float %A) { +; CHECK-LABEL: test2 +; CHECK-NEXT: ret float 0.000000e+00 + + %X = fadd fast float 1.000000e+00, %A + %Y = fadd fast float 1.000000e+00, %A + %r = fsub fast float %X, %Y + ret float %r +} diff --git a/test/Transforms/Reassociate/fast-ArrayOutOfBounds.ll b/test/Transforms/Reassociate/fast-ArrayOutOfBounds.ll new file mode 100644 index 000000000000..0109e4fd1b3a --- /dev/null +++ b/test/Transforms/Reassociate/fast-ArrayOutOfBounds.ll @@ -0,0 +1,65 @@ +; RUN: opt < %s -reassociate -instcombine -S | FileCheck %s + +; Not marked as fast, so must not change. +define float @test1(float %a0, float %a1, float %a2, float %a3, float %a4) { +; CHECK-LABEL: test1 +; CHECK-NEXT: %tmp.2 = fadd float %a3, %a4 +; CHECK-NEXT: %tmp.4 = fadd float %tmp.2, %a2 +; CHECK-NEXT: %tmp.6 = fadd float %tmp.4, %a1 +; CHECK-NEXT: %tmp.8 = fadd float %tmp.6, %a0 +; CHECK-NEXT: %tmp.11 = fadd float %a2, %a3 +; CHECK-NEXT: %tmp.13 = fadd float %tmp.11, %a1 +; CHECK-NEXT: %tmp.15 = fadd float %tmp.13, %a0 +; CHECK-NEXT: %tmp.18 = fadd float %a1, %a2 +; CHECK-NEXT: %tmp.20 = fadd float %tmp.18, %a0 +; CHECK-NEXT: %tmp.23 = fadd float %a0, %a1 +; CHECK-NEXT: %tmp.26 = fsub float %tmp.8, %tmp.15 +; CHECK-NEXT: %tmp.28 = fadd float %tmp.20, %tmp.26 +; CHECK-NEXT: %tmp.30 = fsub float %tmp.28, %tmp.23 +; CHECK-NEXT: %tmp.32 = fsub float %tmp.30, %a4 +; CHECK-NEXT: %tmp.34 = fsub float %tmp.32, %a2 +; CHECK-NEXT: %T = fmul float %tmp.34, %tmp.34 +; CHECK-NEXT: ret float %T + + %tmp.2 = fadd float %a4, %a3 + %tmp.4 = fadd float %tmp.2, %a2 + %tmp.6 = fadd float %tmp.4, %a1 + %tmp.8 = fadd float %tmp.6, %a0 + %tmp.11 = fadd float %a3, %a2 + %tmp.13 = fadd float %tmp.11, %a1 + %tmp.15 = fadd float %tmp.13, %a0 + %tmp.18 = fadd float %a2, %a1 + %tmp.20 = fadd float %tmp.18, %a0 + %tmp.23 = fadd float %a1, %a0 + %tmp.26 = fsub float %tmp.8, %tmp.15 + %tmp.28 = fadd float %tmp.26, %tmp.20 + %tmp.30 = fsub float %tmp.28, %tmp.23 + %tmp.32 = fsub float %tmp.30, %a4 + %tmp.34 = fsub float %tmp.32, %a2 + %T = fmul float %tmp.34, %tmp.34 + ret float %T +} + +; Should be able to eliminate everything. +define float @test2(float %a0, float %a1, float %a2, float %a3, float %a4) { +; CHECK-LABEL: test2 +; CHECK: ret float 0.000000e+00 + + %tmp.2 = fadd fast float %a4, %a3 + %tmp.4 = fadd fast float %tmp.2, %a2 + %tmp.6 = fadd fast float %tmp.4, %a1 + %tmp.8 = fadd fast float %tmp.6, %a0 + %tmp.11 = fadd fast float %a3, %a2 + %tmp.13 = fadd fast float %tmp.11, %a1 + %tmp.15 = fadd fast float %tmp.13, %a0 + %tmp.18 = fadd fast float %a2, %a1 + %tmp.20 = fadd fast float %tmp.18, %a0 + %tmp.23 = fadd fast float %a1, %a0 + %tmp.26 = fsub fast float %tmp.8, %tmp.15 + %tmp.28 = fadd fast float %tmp.26, %tmp.20 + %tmp.30 = fsub fast float %tmp.28, %tmp.23 + %tmp.32 = fsub fast float %tmp.30, %a4 + %tmp.34 = fsub fast float %tmp.32, %a2 + %T = fmul fast float %tmp.34, %tmp.34 + ret float %T +} diff --git a/test/Transforms/Reassociate/fast-MissedTree.ll b/test/Transforms/Reassociate/fast-MissedTree.ll new file mode 100644 index 000000000000..689fd6cad74d --- /dev/null +++ b/test/Transforms/Reassociate/fast-MissedTree.ll @@ -0,0 +1,11 @@ +; RUN: opt < %s -reassociate -instcombine -S | FileCheck %s + +define float @test1(float %A, float %B) { +; CHECK-LABEL: test1 +; CHECK: %Z = fadd fast float %A, %B +; CHECK: ret float %Z + %W = fadd fast float %B, -5.0 + %Y = fadd fast float %A, 5.0 + %Z = fadd fast float %W, %Y + ret float %Z +} diff --git a/test/Transforms/Reassociate/fast-ReassociateVector.ll b/test/Transforms/Reassociate/fast-ReassociateVector.ll new file mode 100644 index 000000000000..eeae096bf944 --- /dev/null +++ b/test/Transforms/Reassociate/fast-ReassociateVector.ll @@ -0,0 +1,73 @@ +; RUN: opt < %s -reassociate -S | FileCheck %s + +; Canonicalize operands, but don't optimize floating point vector operations. +define <4 x float> @test1() { +; CHECK-LABEL: test1 +; CHECK-NEXT: %tmp1 = fsub fast <4 x float> zeroinitializer, zeroinitializer +; CHECK-NEXT: %tmp2 = fmul fast <4 x float> %tmp1, zeroinitializer + + %tmp1 = fsub fast <4 x float> zeroinitializer, zeroinitializer + %tmp2 = fmul fast <4 x float> zeroinitializer, %tmp1 + ret <4 x float> %tmp2 +} + +; Commute integer vector operations. +define <2 x i32> @test2(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: test2 +; CHECK-NEXT: %tmp1 = add <2 x i32> %x, %y +; CHECK-NEXT: %tmp2 = add <2 x i32> %x, %y +; CHECK-NEXT: %tmp3 = add <2 x i32> %tmp1, %tmp2 + + %tmp1 = add <2 x i32> %x, %y + %tmp2 = add <2 x i32> %y, %x + %tmp3 = add <2 x i32> %tmp1, %tmp2 + ret <2 x i32> %tmp3 +} + +define <2 x i32> @test3(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: test3 +; CHECK-NEXT: %tmp1 = mul <2 x i32> %x, %y +; CHECK-NEXT: %tmp2 = mul <2 x i32> %x, %y +; CHECK-NEXT: %tmp3 = mul <2 x i32> %tmp1, %tmp2 + + %tmp1 = mul <2 x i32> %x, %y + %tmp2 = mul <2 x i32> %y, %x + %tmp3 = mul <2 x i32> %tmp1, %tmp2 + ret <2 x i32> %tmp3 +} + +define <2 x i32> @test4(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: test4 +; CHECK-NEXT: %tmp1 = and <2 x i32> %x, %y +; CHECK-NEXT: %tmp2 = and <2 x i32> %x, %y +; CHECK-NEXT: %tmp3 = and <2 x i32> %tmp1, %tmp2 + + %tmp1 = and <2 x i32> %x, %y + %tmp2 = and <2 x i32> %y, %x + %tmp3 = and <2 x i32> %tmp1, %tmp2 + ret <2 x i32> %tmp3 +} + +define <2 x i32> @test5(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: test5 +; CHECK-NEXT: %tmp1 = or <2 x i32> %x, %y +; CHECK-NEXT: %tmp2 = or <2 x i32> %x, %y +; CHECK-NEXT: %tmp3 = or <2 x i32> %tmp1, %tmp2 + + %tmp1 = or <2 x i32> %x, %y + %tmp2 = or <2 x i32> %y, %x + %tmp3 = or <2 x i32> %tmp1, %tmp2 + ret <2 x i32> %tmp3 +} + +define <2 x i32> @test6(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: test6 +; CHECK-NEXT: %tmp1 = xor <2 x i32> %x, %y +; CHECK-NEXT: %tmp2 = xor <2 x i32> %x, %y +; CHECK-NEXT: %tmp3 = xor <2 x i32> %tmp1, %tmp2 + + %tmp1 = xor <2 x i32> %x, %y + %tmp2 = xor <2 x i32> %y, %x + %tmp3 = xor <2 x i32> %tmp1, %tmp2 + ret <2 x i32> %tmp3 +} diff --git a/test/Transforms/Reassociate/fast-SubReassociate.ll b/test/Transforms/Reassociate/fast-SubReassociate.ll new file mode 100644 index 000000000000..db4191a4fa1b --- /dev/null +++ b/test/Transforms/Reassociate/fast-SubReassociate.ll @@ -0,0 +1,70 @@ +; RUN: opt < %s -reassociate -constprop -instcombine -S | FileCheck %s + +define float @test1(float %A, float %B) { +; CHECK-LABEL: test1 +; CHECK-NEXT: %W = fadd float %B, 5.000000e+00 +; CHECK-NEXT: %X = fadd float %A, -7.000000e+00 +; CHECK-NEXT: %Y = fsub float %X, %W +; CHECK-NEXT: %Z = fadd float %Y, 1.200000e+01 +; CHECK-NEXT: ret float %Z + + %W = fadd float 5.0, %B + %X = fadd float -7.0, %A + %Y = fsub float %X, %W + %Z = fadd float %Y, 12.0 + ret float %Z +} + +; With sub reassociation, constant folding can eliminate all of the constants. +define float @test2(float %A, float %B) { +; CHECK-LABEL: test2 +; CHECK-NEXT: %Z = fsub fast float %A, %B +; CHECK-NEXT: ret float %Z + + %W = fadd fast float %B, 5.000000e+00 + %X = fadd fast float %A, -7.000000e+00 + %Y = fsub fast float %X, %W + %Z = fadd fast float %Y, 1.200000e+01 + ret float %Z + +} + +define float @test3(float %A, float %B, float %C, float %D) { +; CHECK-LABEL: test3 +; CHECK-NEXT: %M = fadd float %A, 1.200000e+01 +; CHECK-NEXT: %N = fadd float %M, %B +; CHECK-NEXT: %O = fadd float %N, %C +; CHECK-NEXT: %P = fsub float %D, %O +; CHECK-NEXT: %Q = fadd float %P, 1.200000e+01 +; CHECK-NEXT: ret float %Q + + %M = fadd float %A, 1.200000e+01 + %N = fadd float %M, %B + %O = fadd float %N, %C + %P = fsub float %D, %O + %Q = fadd float %P, 1.200000e+01 + ret float %Q +} + +; With sub reassociation, constant folding can eliminate the two 12 constants. +define float @test4(float %A, float %B, float %C, float %D) { +; CHECK-LABEL: test4 +; CHECK-NEXT: %B.neg = fsub fast float -0.000000e+00, %B +; CHECK-NEXT: %O.neg = fsub fast float %B.neg, %A +; CHECK-NEXT: %P = fsub fast float %O.neg, %C +; CHECK-NEXT: %Q = fadd fast float %P, %D +; CHECK-NEXT: ret float %Q + +; FIXME: InstCombine should be able to get us to the following: +; %sum = fadd fast float %B, %A +; %sum1 = fadd fast float %sum, %C +; %Q = fsub fast float %D, %sum1 +; ret i32 %Q + + %M = fadd fast float 1.200000e+01, %A + %N = fadd fast float %M, %B + %O = fadd fast float %N, %C + %P = fsub fast float %D, %O + %Q = fadd fast float 1.200000e+01, %P + ret float %Q +} diff --git a/test/Transforms/Reassociate/fast-basictest.ll b/test/Transforms/Reassociate/fast-basictest.ll new file mode 100644 index 000000000000..67b07f4d2699 --- /dev/null +++ b/test/Transforms/Reassociate/fast-basictest.ll @@ -0,0 +1,285 @@ +; RUN: opt < %s -reassociate -gvn -instcombine -S | FileCheck %s + +; With reassociation, constant folding can eliminate the 12 and -12 constants. +define float @test1(float %arg) { +; CHECK-LABEL: @test1 +; CHECK-NEXT: fsub fast float -0.000000e+00, %arg +; CHECK-NEXT: ret float + + %tmp1 = fsub fast float -1.200000e+01, %arg + %tmp2 = fadd fast float %tmp1, 1.200000e+01 + ret float %tmp2 +} + +define float @test2(float %reg109, float %reg1111) { +; CHECK-LABEL: @test2 +; CHECK-NEXT: fadd float %reg109, -3.000000e+01 +; CHECK-NEXT: fadd float %reg115, %reg1111 +; CHECK-NEXT: fadd float %reg116, 3.000000e+01 +; CHECK-NEXT: ret float + + %reg115 = fadd float %reg109, -3.000000e+01 + %reg116 = fadd float %reg115, %reg1111 + %reg117 = fadd float %reg116, 3.000000e+01 + ret float %reg117 +} + +define float @test3(float %reg109, float %reg1111) { +; CHECK-LABEL: @test3 +; CHECK-NEXT: %reg117 = fadd fast float %reg109, %reg1111 +; CHECK-NEXT: ret float %reg117 + + %reg115 = fadd fast float %reg109, -3.000000e+01 + %reg116 = fadd fast float %reg115, %reg1111 + %reg117 = fadd fast float %reg116, 3.000000e+01 + ret float %reg117 +} + +@fe = external global float +@fa = external global float +@fb = external global float +@fc = external global float +@ff = external global float + +define void @test4() { +; CHECK-LABEL: @test4 +; CHECK: fadd fast float +; CHECK: fadd fast float +; CHECK-NOT: fadd fast float +; CHECK: ret void + + %A = load float* @fa + %B = load float* @fb + %C = load float* @fc + %t1 = fadd fast float %A, %B + %t2 = fadd fast float %t1, %C + %t3 = fadd fast float %C, %A + %t4 = fadd fast float %t3, %B + ; e = (a+b)+c; + store float %t2, float* @fe + ; f = (a+c)+b + store float %t4, float* @ff + ret void +} + +define void @test5() { +; CHECK-LABEL: @test5 +; CHECK: fadd fast float +; CHECK: fadd fast float +; CHECK-NOT: fadd +; CHECK: ret void + + %A = load float* @fa + %B = load float* @fb + %C = load float* @fc + %t1 = fadd fast float %A, %B + %t2 = fadd fast float %t1, %C + %t3 = fadd fast float %C, %A + %t4 = fadd fast float %t3, %B + ; e = c+(a+b) + store float %t2, float* @fe + ; f = (c+a)+b + store float %t4, float* @ff + ret void +} + +define void @test6() { +; CHECK-LABEL: @test6 +; CHECK: fadd fast float +; CHECK: fadd fast float +; CHECK-NOT: fadd +; CHECK: ret void + + %A = load float* @fa + %B = load float* @fb + %C = load float* @fc + %t1 = fadd fast float %B, %A + %t2 = fadd fast float %t1, %C + %t3 = fadd fast float %C, %A + %t4 = fadd fast float %t3, %B + ; e = c+(b+a) + store float %t2, float* @fe + ; f = (c+a)+b + store float %t4, float* @ff + ret void +} + +define float @test7(float %A, float %B, float %C) { +; CHECK-LABEL: @test7 +; CHECK-NEXT: fadd fast float %C, %B +; CHECK-NEXT: fmul fast float %A, %A +; CHECK-NEXT: fmul fast float %1, %tmp2 +; CHECK-NEXT: ret float + + %aa = fmul fast float %A, %A + %aab = fmul fast float %aa, %B + %ac = fmul fast float %A, %C + %aac = fmul fast float %ac, %A + %r = fadd fast float %aab, %aac + ret float %r +} + +define float @test8(float %X, float %Y, float %Z) { +; CHECK-LABEL: @test8 +; CHECK-NEXT: fmul fast float %Y, %X +; CHECK-NEXT: fsub fast float %Z +; CHECK-NEXT: ret float + + %A = fsub fast float 0.0, %X + %B = fmul fast float %A, %Y + ; (-X)*Y + Z -> Z-X*Y + %C = fadd fast float %B, %Z + ret float %C +} + +define float @test9(float %X) { +; CHECK-LABEL: @test9 +; CHECK-NEXT: fmul fast float %X, 9.400000e+01 +; CHECK-NEXT: ret float + + %Y = fmul fast float %X, 4.700000e+01 + %Z = fadd fast float %Y, %Y + ret float %Z +} + +define float @test10(float %X) { +; CHECK-LABEL: @test10 +; CHECK-NEXT: fmul fast float %X, 3.000000e+00 +; CHECK-NEXT: ret float + + %Y = fadd fast float %X ,%X + %Z = fadd fast float %Y, %X + ret float %Z +} + +define float @test11(float %W) { +; CHECK-LABEL: test11 +; CHECK-NEXT: fmul fast float %W, 3.810000e+02 +; CHECK-NEXT: ret float + + %X = fmul fast float %W, 127.0 + %Y = fadd fast float %X ,%X + %Z = fadd fast float %Y, %X + ret float %Z +} + +define float @test12(float %X) { +; CHECK-LABEL: @test12 +; CHECK-NEXT: fmul fast float %X, -3.000000e+00 +; CHECK-NEXT: fadd fast float %factor, 6.000000e+00 +; CHECK-NEXT: ret float + + %A = fsub fast float 1.000000e+00, %X + %B = fsub fast float 2.000000e+00, %X + %C = fsub fast float 3.000000e+00, %X + %Y = fadd fast float %A ,%B + %Z = fadd fast float %Y, %C + ret float %Z +} + +define float @test13(float %X1, float %X2, float %X3) { +; CHECK-LABEL: @test13 +; CHECK-NEXT: fsub fast float %X3, %X2 +; CHECK-NEXT: fmul fast float {{.*}}, %X1 +; CHECK-NEXT: ret float + + %A = fsub fast float 0.000000e+00, %X1 + %B = fmul fast float %A, %X2 ; -X1*X2 + %C = fmul fast float %X1, %X3 ; X1*X3 + %D = fadd fast float %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2) + ret float %D +} + +define float @test14(float %X1, float %X2) { +; CHECK-LABEL: @test14 +; CHECK-NEXT: fsub fast float %X1, %X2 +; CHECK-NEXT: fmul fast float %1, 4.700000e+01 +; CHECK-NEXT: ret float + + %B = fmul fast float %X1, 47. ; X1*47 + %C = fmul fast float %X2, -47. ; X2*-47 + %D = fadd fast float %B, %C ; X1*47 + X2*-47 -> 47*(X1-X2) + ret float %D +} + +define float @test15(float %arg) { +; CHECK-LABEL: test15 +; CHECK-NEXT: fmul fast float %arg, 1.440000e+02 +; CHECK-NEXT: ret float %tmp2 + + %tmp1 = fmul fast float 1.200000e+01, %arg + %tmp2 = fmul fast float %tmp1, 1.200000e+01 + ret float %tmp2 +} + +; (b+(a+1234))+-a -> b+1234 +define float @test16(float %b, float %a) { +; CHECK-LABEL: @test16 +; CHECK-NEXT: fadd fast float %b, 1.234000e+03 +; CHECK-NEXT: ret float + + %1 = fadd fast float %a, 1234.0 + %2 = fadd fast float %b, %1 + %3 = fsub fast float 0.0, %a + %4 = fadd fast float %2, %3 + ret float %4 +} + +; Test that we can turn things like X*-(Y*Z) -> X*-1*Y*Z. + +define float @test17(float %a, float %b, float %z) { +; CHECK-LABEL: test17 +; CHECK-NEXT: fmul fast float %a, 1.234500e+04 +; CHECK-NEXT: fmul fast float %e, %b +; CHECK-NEXT: fmul fast float %f, %z +; CHECK-NEXT: ret float + + %c = fsub fast float 0.000000e+00, %z + %d = fmul fast float %a, %b + %e = fmul fast float %c, %d + %f = fmul fast float %e, 1.234500e+04 + %g = fsub fast float 0.000000e+00, %f + ret float %g +} + +define float @test18(float %a, float %b, float %z) { +; CHECK-LABEL: test18 +; CHECK-NEXT: fmul fast float %a, 4.000000e+01 +; CHECK-NEXT: fmul fast float %e, %z +; CHECK-NEXT: ret float + + %d = fmul fast float %z, 4.000000e+01 + %c = fsub fast float 0.000000e+00, %d + %e = fmul fast float %a, %c + %f = fsub fast float 0.000000e+00, %e + ret float %f +} + +; With sub reassociation, constant folding can eliminate the 12 and -12 constants. +define float @test19(float %A, float %B) { +; CHECK-LABEL: @test19 +; CHECK-NEXT: fsub fast float %A, %B +; CHECK-NEXT: ret float + %X = fadd fast float -1.200000e+01, %A + %Y = fsub fast float %X, %B + %Z = fadd fast float %Y, 1.200000e+01 + ret float %Z +} + +; With sub reassociation, constant folding can eliminate the uses of %a. +define float @test20(float %a, float %b, float %c) nounwind { +; CHECK-LABEL: @test20 +; CHECK-NEXT: fsub fast float -0.000000e+00, %b +; CHECK-NEXT: fsub fast float %b.neg, %c +; CHECK-NEXT: ret float + +; FIXME: Should be able to generate the below, which may expose more +; opportunites for FAdd reassociation. +; %sum = fadd fast float %c, %b +; %tmp7 = fsub fast float 0, %sum + + %tmp3 = fsub fast float %a, %b + %tmp5 = fsub fast float %tmp3, %c + %tmp7 = fsub fast float %tmp5, %a + ret float %tmp7 +} diff --git a/test/Transforms/Reassociate/fast-fp-commute.ll b/test/Transforms/Reassociate/fast-fp-commute.ll new file mode 100644 index 000000000000..ad89607a21e4 --- /dev/null +++ b/test/Transforms/Reassociate/fast-fp-commute.ll @@ -0,0 +1,44 @@ +; RUN: opt -reassociate -S < %s | FileCheck %s + +declare void @use(float) + +define void @test1(float %x, float %y) { +; CHECK-LABEL: test1 +; CHECK: fmul fast float %y, %x +; CHECK: fmul fast float %y, %x +; CHECK: fsub fast float %1, %2 +; CHECK: call void @use(float %{{.*}}) +; CHECK: call void @use(float %{{.*}}) + + %1 = fmul fast float %x, %y + %2 = fmul fast float %y, %x + %3 = fsub fast float %1, %2 + call void @use(float %1) + call void @use(float %3) + ret void +} + +define float @test2(float %x, float %y) { +; CHECK-LABEL: test2 +; CHECK-NEXT: fmul fast float %y, %x +; CHECK-NEXT: fmul fast float %y, %x +; CHECK-NEXT: fsub fast float %1, %2 +; CHECK-NEXT: ret float %3 + + %1 = fmul fast float %x, %y + %2 = fmul fast float %y, %x + %3 = fsub fast float %1, %2 + ret float %3 +} + +define float @test3(float %x, float %y) { +; CHECK-LABEL: test3 +; CHECK-NEXT: %factor = fmul fast float %y, 2.000000e+00 +; CHECK-NEXT: %tmp1 = fmul fast float %factor, %x +; CHECK-NEXT: ret float %tmp1 + + %1 = fmul fast float %x, %y + %2 = fmul fast float %y, %x + %3 = fadd fast float %1, %2 + ret float %3 +} diff --git a/test/Transforms/Reassociate/fast-mightymul.ll b/test/Transforms/Reassociate/fast-mightymul.ll new file mode 100644 index 000000000000..98bdf7a55ace --- /dev/null +++ b/test/Transforms/Reassociate/fast-mightymul.ll @@ -0,0 +1,35 @@ +; RUN: opt < %s -reassociate -disable-output +; PR13021 + +define float @test2(float %x) { + %t0 = fmul fast float %x, %x + %t1 = fmul fast float %t0, %t0 + %t2 = fmul fast float %t1, %t1 + %t3 = fmul fast float %t2, %t2 + %t4 = fmul fast float %t3, %t3 + %t5 = fmul fast float %t4, %t4 + %t6 = fmul fast float %t5, %t5 + %t7 = fmul fast float %t6, %t6 + %t8 = fmul fast float %t7, %t7 + %t9 = fmul fast float %t8, %t8 + %t10 = fmul fast float %t9, %t9 + %t11 = fmul fast float %t10, %t10 + %t12 = fmul fast float %t11, %t11 + %t13 = fmul fast float %t12, %t12 + %t14 = fmul fast float %t13, %t13 + %t15 = fmul fast float %t14, %t14 + %t16 = fmul fast float %t15, %t15 + %t17 = fmul fast float %t16, %t16 + %t18 = fmul fast float %t17, %t17 + %t19 = fmul fast float %t18, %t18 + %t20 = fmul fast float %t19, %t19 + %t21 = fmul fast float %t20, %t20 + %t22 = fmul fast float %t21, %t21 + %t23 = fmul fast float %t22, %t22 + %t24 = fmul fast float %t23, %t23 + %t25 = fmul fast float %t24, %t24 + %t26 = fmul fast float %t25, %t25 + %t27 = fmul fast float %t26, %t26 + %t28 = fmul fast float %t27, %t27 + ret float %t28 +} diff --git a/test/Transforms/Reassociate/fast-multistep.ll b/test/Transforms/Reassociate/fast-multistep.ll new file mode 100644 index 000000000000..45e15c7f3539 --- /dev/null +++ b/test/Transforms/Reassociate/fast-multistep.ll @@ -0,0 +1,32 @@ +; RUN: opt < %s -reassociate -S | FileCheck %s + +define float @fmultistep1(float %a, float %b, float %c) { +; Check that a*a*b+a*a*c is turned into a*(a*(b+c)). +; CHECK-LABEL: @fmultistep1 +; CHECK-NEXT: fadd fast float %c, %b +; CHECK-NEXT: fmul fast float %a, %tmp2 +; CHECK-NEXT: fmul fast float %tmp3, %a +; CHECK-NEXT: ret float + + %t0 = fmul fast float %a, %b + %t1 = fmul fast float %a, %t0 ; a*(a*b) + %t2 = fmul fast float %a, %c + %t3 = fmul fast float %a, %t2 ; a*(a*c) + %t4 = fadd fast float %t1, %t3 + ret float %t4 +} + +define float @fmultistep2(float %a, float %b, float %c, float %d) { +; Check that a*b+a*c+d is turned into a*(b+c)+d. +; CHECK-LABEL: @fmultistep2 +; CHECK-NEXT: fadd fast float %c, %b +; CHECK-NEXT: fmul fast float %tmp, %a +; CHECK-NEXT: fadd fast float %tmp1, %d +; CHECK-NEXT: ret float + + %t0 = fmul fast float %a, %b + %t1 = fmul fast float %a, %c + %t2 = fadd fast float %t1, %d ; a*c+d + %t3 = fadd fast float %t0, %t2 ; a*b+(a*c+d) + ret float %t3 +} diff --git a/test/Transforms/Reassociate/mixed-fast-nonfast-fp.ll b/test/Transforms/Reassociate/mixed-fast-nonfast-fp.ll new file mode 100644 index 000000000000..f51c0c17fe7d --- /dev/null +++ b/test/Transforms/Reassociate/mixed-fast-nonfast-fp.ll @@ -0,0 +1,18 @@ +; RUN: opt -reassociate %s -S | FileCheck %s + +define float @foo(float %a,float %b, float %c) { +; CHECK: %mul3 = fmul float %a, %b +; CHECK-NEXT: fmul fast float %c, 2.000000e+00 +; CHECK-NEXT: fadd fast float %factor, %b +; CHECK-NEXT: fmul fast float %tmp1, %a +; CHECK-NEXT: fadd fast float %tmp2, %mul3 +; CHECK-NEXT: ret float + %mul1 = fmul fast float %a, %c + %mul2 = fmul fast float %a, %b + %mul3 = fmul float %a, %b + %mul4 = fmul fast float %a, %c + %add1 = fadd fast float %mul1, %mul3 + %add2 = fadd fast float %mul4, %mul2 + %add3 = fadd fast float %add1, %add2 + ret float %add3 +} diff --git a/test/Transforms/Reassociate/multistep.ll b/test/Transforms/Reassociate/multistep.ll index 12eaeeea7b7b..c499646a8b6a 100644 --- a/test/Transforms/Reassociate/multistep.ll +++ b/test/Transforms/Reassociate/multistep.ll @@ -9,7 +9,7 @@ define i64 @multistep1(i64 %a, i64 %b, i64 %c) { %t3 = mul i64 %a, %t2 ; a*(a*c) %t4 = add i64 %t1, %t3 ; CHECK-NEXT: add i64 %c, %b -; CHECK-NEXT: mul i64 %tmp{{.*}}, %a +; CHECK-NEXT: mul i64 %a, %tmp{{.*}} ; CHECK-NEXT: mul i64 %tmp{{.*}}, %a ; CHECK-NEXT: ret ret i64 %t4 diff --git a/test/Transforms/Reassociate/negation1.ll b/test/Transforms/Reassociate/negation1.ll new file mode 100644 index 000000000000..34b943cf496d --- /dev/null +++ b/test/Transforms/Reassociate/negation1.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -reassociate -instcombine -S | FileCheck %s + +; Test that we can turn things like A*B + X - A*B -> X. + +define i32 @test1(i32 %a, i32 %b, i32 %x) { +; CHECK-LABEL: test1 +; CHECK: ret i32 %x + + %c = mul i32 %a, %b + %d = add i32 %c, %x + %c1 = mul i32 %a, %b + %f = sub i32 %d, %c1 + ret i32 %f +} + diff --git a/test/Transforms/Reassociate/pr21205.ll b/test/Transforms/Reassociate/pr21205.ll new file mode 100644 index 000000000000..fcc7150478eb --- /dev/null +++ b/test/Transforms/Reassociate/pr21205.ll @@ -0,0 +1,21 @@ +; RUN: opt -reassociate -S < %s | FileCheck %s +; PR21205 + +@a = common global i32 0, align 4 +@b = common global i32 0, align 4 + +; Don't canonicalize %conv - undef into %conv + (-undef). +; CHECK-LABEL: @test1 +; CHECK: %sub = fsub fast float %conv, undef +; CHECK: %sub1 = fadd fast float %sub, -1.000000e+00 + +define i32 @test1() { +entry: + %0 = load i32* @a, align 4 + %conv = sitofp i32 %0 to float + %sub = fsub fast float %conv, undef + %sub1 = fadd fast float %sub, -1.000000e+00 + %conv2 = fptosi float %sub1 to i32 + store i32 %conv2, i32* @b, align 4 + ret i32 undef +} diff --git a/test/Transforms/Reassociate/wrap-flags.ll b/test/Transforms/Reassociate/wrap-flags.ll new file mode 100644 index 000000000000..e3304b6a7bb2 --- /dev/null +++ b/test/Transforms/Reassociate/wrap-flags.ll @@ -0,0 +1,34 @@ +; RUN: opt < %s -reassociate -dce -S | FileCheck %s +; PR12985 + +; Verify the nsw flags are preserved when converting shl to mul. + +; CHECK-LABEL: @shl_to_mul_nsw( +; CHECK: %mul = mul i32 %i, -2147483648 +; CHECK: add i32 %mul, 1 +define i32 @shl_to_mul_nsw(i32 %i) { +entry: + %mul = shl nsw i32 %i, 31 + %mul2 = add i32 %mul, 1 + ret i32 %mul2 +} + +; CHECK-LABEL: @shl_to_mul_nuw( +; CHECK: %mul = mul nuw i32 %i, 4 +; CHECK: add i32 %mul, 1 +define i32 @shl_to_mul_nuw(i32 %i) { +entry: + %mul = shl nuw i32 %i, 2 + %mul2 = add i32 %mul, 1 + ret i32 %mul2 +} + +; CHECK-LABEL: @shl_to_mul_nuw_nsw( +; CHECK: %mul = mul nuw nsw i32 %i, 4 +; CHECK: add i32 %mul, 1 +define i32 @shl_to_mul_nuw_nsw(i32 %i) { +entry: + %mul = shl nuw nsw i32 %i, 2 + %mul2 = add i32 %mul, 1 + ret i32 %mul2 +} diff --git a/test/Transforms/SCCP/ipsccp-basic.ll b/test/Transforms/SCCP/ipsccp-basic.ll index c1c6c926fd9b..107b7af2c1dc 100644 --- a/test/Transforms/SCCP/ipsccp-basic.ll +++ b/test/Transforms/SCCP/ipsccp-basic.ll @@ -227,3 +227,23 @@ entry: ; CHECK-LABEL: define internal i32 @test10b( ; CHECK: ret i32 undef } + +;;======================== test11 + +define i64 @test11a() { + %xor = xor i64 undef, undef + ret i64 %xor +; CHECK-LABEL: define i64 @test11a +; CHECK: ret i64 0 +} + +define void @test11b() { + %call1 = call i64 @test11a() + %call2 = call i64 @llvm.ctpop.i64(i64 %call1) + ret void +; CHECK-LABEL: define void @test11b +; CHECK: %[[call1:.*]] = call i64 @test11a() +; CHECK: %[[call2:.*]] = call i64 @llvm.ctpop.i64(i64 0) +} + +declare i64 @llvm.ctpop.i64(i64) diff --git a/test/Transforms/SLPVectorizer/AArch64/commute.ll b/test/Transforms/SLPVectorizer/AArch64/commute.ll new file mode 100644 index 000000000000..4ee91a5ed4c0 --- /dev/null +++ b/test/Transforms/SLPVectorizer/AArch64/commute.ll @@ -0,0 +1,75 @@ +; RUN: opt -S -slp-vectorizer %s | FileCheck %s +target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-gnu" + +%structA = type { [2 x float] } + +define void @test1(%structA* nocapture readonly %J, i32 %xmin, i32 %ymin) { +; CHECK-LABEL: test1 +; CHECK: %arrayidx4 = getelementptr inbounds %structA* %J, i64 0, i32 0, i64 0 +; CHECK: %arrayidx9 = getelementptr inbounds %structA* %J, i64 0, i32 0, i64 1 +; CHECK: %3 = bitcast float* %arrayidx4 to <2 x float>* +; CHECK: %4 = load <2 x float>* %3, align 4 +; CHECK: %5 = fsub fast <2 x float> %2, %4 +; CHECK: %6 = fmul fast <2 x float> %5, %5 +; CHECK: %7 = extractelement <2 x float> %6, i32 0 +; CHECK: %8 = extractelement <2 x float> %6, i32 1 +; CHECK: %add = fadd fast float %7, %8 +; CHECK: %cmp = fcmp oeq float %add, 0.000000e+00 + +entry: + br label %for.body3.lr.ph + +for.body3.lr.ph: + %conv5 = sitofp i32 %ymin to float + %conv = sitofp i32 %xmin to float + %arrayidx4 = getelementptr inbounds %structA* %J, i64 0, i32 0, i64 0 + %0 = load float* %arrayidx4, align 4 + %sub = fsub fast float %conv, %0 + %arrayidx9 = getelementptr inbounds %structA* %J, i64 0, i32 0, i64 1 + %1 = load float* %arrayidx9, align 4 + %sub10 = fsub fast float %conv5, %1 + %mul11 = fmul fast float %sub, %sub + %mul12 = fmul fast float %sub10, %sub10 + %add = fadd fast float %mul11, %mul12 + %cmp = fcmp oeq float %add, 0.000000e+00 + br i1 %cmp, label %for.body3.lr.ph, label %for.end27 + +for.end27: + ret void +} + +define void @test2(%structA* nocapture readonly %J, i32 %xmin, i32 %ymin) { +; CHECK-LABEL: test2 +; CHECK: %arrayidx4 = getelementptr inbounds %structA* %J, i64 0, i32 0, i64 0 +; CHECK: %arrayidx9 = getelementptr inbounds %structA* %J, i64 0, i32 0, i64 1 +; CHECK: %3 = bitcast float* %arrayidx4 to <2 x float>* +; CHECK: %4 = load <2 x float>* %3, align 4 +; CHECK: %5 = fsub fast <2 x float> %2, %4 +; CHECK: %6 = fmul fast <2 x float> %5, %5 +; CHECK: %7 = extractelement <2 x float> %6, i32 0 +; CHECK: %8 = extractelement <2 x float> %6, i32 1 +; CHECK: %add = fadd fast float %8, %7 +; CHECK: %cmp = fcmp oeq float %add, 0.000000e+00 + +entry: + br label %for.body3.lr.ph + +for.body3.lr.ph: + %conv5 = sitofp i32 %ymin to float + %conv = sitofp i32 %xmin to float + %arrayidx4 = getelementptr inbounds %structA* %J, i64 0, i32 0, i64 0 + %0 = load float* %arrayidx4, align 4 + %sub = fsub fast float %conv, %0 + %arrayidx9 = getelementptr inbounds %structA* %J, i64 0, i32 0, i64 1 + %1 = load float* %arrayidx9, align 4 + %sub10 = fsub fast float %conv5, %1 + %mul11 = fmul fast float %sub, %sub + %mul12 = fmul fast float %sub10, %sub10 + %add = fadd fast float %mul12, %mul11 ;;;<---- Operands commuted!! + %cmp = fcmp oeq float %add, 0.000000e+00 + br i1 %cmp, label %for.body3.lr.ph, label %for.end27 + +for.end27: + ret void +} diff --git a/test/Transforms/SLPVectorizer/AArch64/load-store-q.ll b/test/Transforms/SLPVectorizer/AArch64/load-store-q.ll new file mode 100644 index 000000000000..45fa2f917f3a --- /dev/null +++ b/test/Transforms/SLPVectorizer/AArch64/load-store-q.ll @@ -0,0 +1,46 @@ +; RUN: opt -S -basicaa -slp-vectorizer < %s | FileCheck %s +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "arm64-apple-ios5.0.0" + +; Holding a value live over a call boundary may require +; spills and fills. This is the case for <2 x double>, +; as it occupies a Q register of which there are no +; callee-saves. + +; CHECK: load double +; CHECK: load double +; CHECK: call void @g +; CHECK: store double +; CHECK: store double +define void @f(double* %p, double* %q) { + %addr2 = getelementptr double* %q, i32 1 + %addr = getelementptr double* %p, i32 1 + %x = load double* %p + %y = load double* %addr + call void @g() + store double %x, double* %q + store double %y, double* %addr2 + ret void +} +declare void @g() + +; Check we deal with loops correctly. +; +; CHECK: store <2 x double> +; CHECK: load <2 x double> +define void @f2(double* %p, double* %q) { +entry: + br label %loop + +loop: + %p1 = phi double [0.0, %entry], [%x, %loop] + %p2 = phi double [0.0, %entry], [%y, %loop] + %addr2 = getelementptr double* %q, i32 1 + %addr = getelementptr double* %p, i32 1 + store double %p1, double* %q + store double %p2, double* %addr2 + + %x = load double* %p + %y = load double* %addr + br label %loop +} diff --git a/test/Transforms/SLPVectorizer/AArch64/sdiv-pow2.ll b/test/Transforms/SLPVectorizer/AArch64/sdiv-pow2.ll new file mode 100644 index 000000000000..e49c7adda400 --- /dev/null +++ b/test/Transforms/SLPVectorizer/AArch64/sdiv-pow2.ll @@ -0,0 +1,42 @@ +; RUN: opt < %s -basicaa -slp-vectorizer -S -mtriple=aarch64-unknown-linux-gnu -mcpu=cortex-a57 | FileCheck %s +target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-gnu" + +; CHECK-LABEL: @test1 +; CHECK: load <4 x i32> +; CHECK: add nsw <4 x i32> +; CHECK: sdiv <4 x i32> + +define void @test1(i32* noalias nocapture %a, i32* noalias nocapture readonly %b, i32* noalias nocapture readonly %c) { +entry: + %0 = load i32* %b, align 4 + %1 = load i32* %c, align 4 + %add = add nsw i32 %1, %0 + %div = sdiv i32 %add, 2 + store i32 %div, i32* %a, align 4 + %arrayidx3 = getelementptr inbounds i32* %b, i64 1 + %2 = load i32* %arrayidx3, align 4 + %arrayidx4 = getelementptr inbounds i32* %c, i64 1 + %3 = load i32* %arrayidx4, align 4 + %add5 = add nsw i32 %3, %2 + %div6 = sdiv i32 %add5, 2 + %arrayidx7 = getelementptr inbounds i32* %a, i64 1 + store i32 %div6, i32* %arrayidx7, align 4 + %arrayidx8 = getelementptr inbounds i32* %b, i64 2 + %4 = load i32* %arrayidx8, align 4 + %arrayidx9 = getelementptr inbounds i32* %c, i64 2 + %5 = load i32* %arrayidx9, align 4 + %add10 = add nsw i32 %5, %4 + %div11 = sdiv i32 %add10, 2 + %arrayidx12 = getelementptr inbounds i32* %a, i64 2 + store i32 %div11, i32* %arrayidx12, align 4 + %arrayidx13 = getelementptr inbounds i32* %b, i64 3 + %6 = load i32* %arrayidx13, align 4 + %arrayidx14 = getelementptr inbounds i32* %c, i64 3 + %7 = load i32* %arrayidx14, align 4 + %add15 = add nsw i32 %7, %6 + %div16 = sdiv i32 %add15, 2 + %arrayidx17 = getelementptr inbounds i32* %a, i64 3 + store i32 %div16, i32* %arrayidx17, align 4 + ret void +} diff --git a/test/Transforms/SLPVectorizer/ARM/sroa.ll b/test/Transforms/SLPVectorizer/ARM/sroa.ll index e0c75b147f6f..899cfb1f82cf 100644 --- a/test/Transforms/SLPVectorizer/ARM/sroa.ll +++ b/test/Transforms/SLPVectorizer/ARM/sroa.ll @@ -5,11 +5,11 @@ target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64- %class.Complex = type { double, double } ; Code like this is the result of SROA. Make sure we don't vectorize this -; because the in the scalar version of this the shl/or are handled by the +; because the scalar version of the shl/or are handled by the ; backend and disappear, the vectorized code stays. ; CHECK-LABEL: SROAed -; CHECK-NOT: shl <2 x i64> +; CHECK-NOT: shl nuw <2 x i64> ; CHECK-NOT: or <2 x i64> define void @SROAed(%class.Complex* noalias nocapture sret %agg.result, [4 x i32] %a.coerce, [4 x i32] %b.coerce) { diff --git a/test/Transforms/SLPVectorizer/X86/addsub.ll b/test/Transforms/SLPVectorizer/X86/addsub.ll index 8303bc8181ef..174d40046849 100644 --- a/test/Transforms/SLPVectorizer/X86/addsub.ll +++ b/test/Transforms/SLPVectorizer/X86/addsub.ll @@ -12,9 +12,9 @@ target triple = "x86_64-unknown-linux-gnu" @fa = common global [4 x float] zeroinitializer, align 16 ; CHECK-LABEL: @addsub -; CHECK: %5 = add <4 x i32> %3, %4 -; CHECK: %6 = add <4 x i32> %2, %5 -; CHECK: %7 = sub <4 x i32> %2, %5 +; CHECK: %5 = add nsw <4 x i32> %3, %4 +; CHECK: %6 = add nsw <4 x i32> %2, %5 +; CHECK: %7 = sub nsw <4 x i32> %2, %5 ; CHECK: %8 = shufflevector <4 x i32> %6, <4 x i32> %7, <4 x i32> <i32 0, i32 5, i32 2, i32 7> ; Function Attrs: nounwind uwtable @@ -56,9 +56,9 @@ entry: } ; CHECK-LABEL: @subadd -; CHECK: %5 = add <4 x i32> %3, %4 -; CHECK: %6 = sub <4 x i32> %2, %5 -; CHECK: %7 = add <4 x i32> %2, %5 +; CHECK: %5 = add nsw <4 x i32> %3, %4 +; CHECK: %6 = sub nsw <4 x i32> %2, %5 +; CHECK: %7 = add nsw <4 x i32> %2, %5 ; CHECK: %8 = shufflevector <4 x i32> %6, <4 x i32> %7, <4 x i32> <i32 0, i32 5, i32 2, i32 7> ; Function Attrs: nounwind uwtable diff --git a/test/Transforms/SLPVectorizer/X86/align.ll b/test/Transforms/SLPVectorizer/X86/align.ll index f5865733ccb5..ce8062025064 100644 --- a/test/Transforms/SLPVectorizer/X86/align.ll +++ b/test/Transforms/SLPVectorizer/X86/align.ll @@ -4,7 +4,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 target triple = "x86_64-apple-macosx10.8.0" ; Simple 3-pair chain with loads and stores -; CHECK: test1 +; CHECK-LABEL: @test1 define void @test1(double* %a, double* %b, double* %c) { entry: %agg.tmp.i.i.sroa.0 = alloca [3 x double], align 16 @@ -25,3 +25,31 @@ entry: ; CHECK: ret ret void } + +; Float has 4 byte abi alignment on x86_64. We must use the alignmnet of the +; value being loaded/stored not the alignment of the pointer type. + +; CHECK-LABEL: @test2 +; CHECK-NOT: align 8 +; CHECK: load <4 x float>{{.*}}, align 4 +; CHECK: store <4 x float>{{.*}}, align 4 +; CHECK: ret + +define void @test2(float * %a, float * %b) { +entry: + %l0 = load float* %a + %a1 = getelementptr inbounds float* %a, i64 1 + %l1 = load float* %a1 + %a2 = getelementptr inbounds float* %a, i64 2 + %l2 = load float* %a2 + %a3 = getelementptr inbounds float* %a, i64 3 + %l3 = load float* %a3 + store float %l0, float* %b + %b1 = getelementptr inbounds float* %b, i64 1 + store float %l1, float* %b1 + %b2 = getelementptr inbounds float* %b, i64 2 + store float %l2, float* %b2 + %b3 = getelementptr inbounds float* %b, i64 3 + store float %l3, float* %b3 + ret void +} diff --git a/test/Transforms/SLPVectorizer/X86/consecutive-access.ll b/test/Transforms/SLPVectorizer/X86/consecutive-access.ll index f4f112fe32c6..aa59429a77d1 100644 --- a/test/Transforms/SLPVectorizer/X86/consecutive-access.ll +++ b/test/Transforms/SLPVectorizer/X86/consecutive-access.ll @@ -172,4 +172,4 @@ attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-po !llvm.ident = !{!0} -!0 = metadata !{metadata !"clang version 3.5.0 "} +!0 = !{!"clang version 3.5.0 "} diff --git a/test/Transforms/SLPVectorizer/X86/crash_binaryop.ll b/test/Transforms/SLPVectorizer/X86/crash_binaryop.ll new file mode 100644 index 000000000000..dc99366e1da7 --- /dev/null +++ b/test/Transforms/SLPVectorizer/X86/crash_binaryop.ll @@ -0,0 +1,41 @@ +; RUN: opt < %s -basicaa -slp-vectorizer -S -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7 + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin13.3.0" + +@a = common global double 0.000000e+00, align 8 + +define i32 @fn1() { +entry: + %init = load double* @a, align 8 + br label %loop + +loop: + %phi = phi double [ %add2, %loop ], [ %init, %entry ] + %postadd1_phi = phi double [ %postadd1, %loop ], [ %init, %entry ] + %postadd2_phi = phi double [ %postadd2, %loop ], [ %init, %entry ] + %add1 = fadd double %postadd1_phi, undef + %add2 = fadd double %postadd2_phi, %phi + %mul2 = fmul double %add2, 0.000000e+00 + %binaryop_B = fadd double %postadd1_phi, %mul2 + %mul1 = fmul double %add1, 0.000000e+00 + %tmp = fadd double %postadd2_phi, 0.000000e+00 + + ; tryToVectorize() starts with this binary instruction. + ; At the same time vectorization wraps around the loop, vectorizes + ; postadd1/2 and eventually binary_V and tmp. So binary_V itself is replaced + ; with a vector instruction. + ; The SLPVectorizer crashed because it tried to use binary_V + ; after vectorization to re-arrange instructions. + %binary_V = fadd double %mul1, %binaryop_B + + %postadd1 = fadd double %binary_V, 0.000000e+00 + %postadd2 = fadd double %tmp, 1.000000e+00 + %tobool = fcmp une double %postadd1, 0.000000e+00 + br i1 %tobool, label %exit, label %loop + +exit: + ret i32 1 +} + + diff --git a/test/Transforms/SLPVectorizer/X86/crash_gep.ll b/test/Transforms/SLPVectorizer/X86/crash_gep.ll new file mode 100644 index 000000000000..dd4034c116e4 --- /dev/null +++ b/test/Transforms/SLPVectorizer/X86/crash_gep.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -basicaa -slp-vectorizer -dce -S -mtriple=x86_64-unknown-linux-gnu + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@a = common global i64* null, align 8 + +; Function Attrs: nounwind uwtable +define i32 @fn1() { +entry: + %0 = load i64** @a, align 8 + %add.ptr = getelementptr inbounds i64* %0, i64 1 + %1 = ptrtoint i64* %add.ptr to i64 + %arrayidx = getelementptr inbounds i64* %0, i64 2 + store i64 %1, i64* %arrayidx, align 8 + %2 = ptrtoint i64* %arrayidx to i64 + store i64 %2, i64* %add.ptr, align 8 + ret i32 undef +} diff --git a/test/Transforms/SLPVectorizer/X86/crash_scheduling.ll b/test/Transforms/SLPVectorizer/X86/crash_scheduling.ll new file mode 100644 index 000000000000..e6cc0f783d79 --- /dev/null +++ b/test/Transforms/SLPVectorizer/X86/crash_scheduling.ll @@ -0,0 +1,47 @@ +; RUN: opt < %s -basicaa -slp-vectorizer -S -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7 + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin13.3.0" + +define void @_foo(double %p1, double %p2, double %p3) #0 { +entry: + %tab1 = alloca [256 x i32], align 16 + %tab2 = alloca [256 x i32], align 16 + br label %bb1 + + +bb1: + %mul19 = fmul double %p1, 1.638400e+04 + %mul20 = fmul double %p3, 1.638400e+04 + %add = fadd double %mul20, 8.192000e+03 + %mul21 = fmul double %p2, 1.638400e+04 + ; The SLPVectorizer crashed when scheduling this block after it inserted an + ; insertelement instruction (during vectorizing the for.body block) at this position. + br label %for.body + +for.body: + %indvars.iv266 = phi i64 [ 0, %bb1 ], [ %indvars.iv.next267, %for.body ] + %t.0259 = phi double [ 0.000000e+00, %bb1 ], [ %add27, %for.body ] + %p3.addr.0258 = phi double [ %add, %bb1 ], [ %add28, %for.body ] + %vecinit.i.i237 = insertelement <2 x double> undef, double %t.0259, i32 0 + %x13 = tail call i32 @_xfn(<2 x double> %vecinit.i.i237) #2 + %arrayidx = getelementptr inbounds [256 x i32]* %tab1, i64 0, i64 %indvars.iv266 + store i32 %x13, i32* %arrayidx, align 4, !tbaa !4 + %vecinit.i.i = insertelement <2 x double> undef, double %p3.addr.0258, i32 0 + %x14 = tail call i32 @_xfn(<2 x double> %vecinit.i.i) #2 + %arrayidx26 = getelementptr inbounds [256 x i32]* %tab2, i64 0, i64 %indvars.iv266 + store i32 %x14, i32* %arrayidx26, align 4, !tbaa !4 + %add27 = fadd double %mul19, %t.0259 + %add28 = fadd double %mul21, %p3.addr.0258 + %indvars.iv.next267 = add nuw nsw i64 %indvars.iv266, 1 + %exitcond = icmp eq i64 %indvars.iv.next267, 256 + br i1 %exitcond, label %return, label %for.body + +return: + ret void +} + +declare i32 @_xfn(<2 x double>) #4 + +!3 = !{!"int", !4, i64 0} +!4 = !{!3, !3, i64 0} diff --git a/test/Transforms/SLPVectorizer/X86/crash_vectorizeTree.ll b/test/Transforms/SLPVectorizer/X86/crash_vectorizeTree.ll index c7ec98adf135..9f1fb71e096f 100644 --- a/test/Transforms/SLPVectorizer/X86/crash_vectorizeTree.ll +++ b/test/Transforms/SLPVectorizer/X86/crash_vectorizeTree.ll @@ -1,4 +1,4 @@ -; RUN: opt -slp-vectorizer -mtriple=x86_64-apple-macosx10.9.0 -mcpu=corei7-avx -S < %s | FileCheck %s +; RUN: opt -basicaa -slp-vectorizer -mtriple=x86_64-apple-macosx10.9.0 -mcpu=corei7-avx -S < %s | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.9.0" diff --git a/test/Transforms/SLPVectorizer/X86/cycle_dup.ll b/test/Transforms/SLPVectorizer/X86/cycle_dup.ll index fba35499fb7d..bac2c3c0df34 100644 --- a/test/Transforms/SLPVectorizer/X86/cycle_dup.ll +++ b/test/Transforms/SLPVectorizer/X86/cycle_dup.ll @@ -15,7 +15,7 @@ target triple = "x86_64-apple-macosx10.9.0" ;CHECK: bitcast i32* %A to <4 x i32>* ;CHECK-NEXT: load <4 x i32> ;CHECK: phi <4 x i32> -;CHECK-NEXT: mul <4 x i32> +;CHECK-NEXT: mul nsw <4 x i32> ;CHECK-NOT: mul ;CHECK: phi <4 x i32> ;CHECK: bitcast i32* %A to <4 x i32>* diff --git a/test/Transforms/SLPVectorizer/X86/debug_info.ll b/test/Transforms/SLPVectorizer/X86/debug_info.ll index f4e68f217f25..21f51d7c6125 100644 --- a/test/Transforms/SLPVectorizer/X86/debug_info.ll +++ b/test/Transforms/SLPVectorizer/X86/debug_info.ll @@ -18,16 +18,16 @@ target triple = "x86_64-apple-macosx10.7.0" ;CHECK: load <2 x double>* {{.*}}, !dbg ![[LOC]] ;CHECK: store <2 x double> {{.*}}, !dbg ![[LOC2:[0-9]+]] ;CHECK: ret -;CHECK: ![[LOC]] = metadata !{i32 4, i32 0, -;CHECK: ![[LOC2]] = metadata !{i32 7, i32 0, +;CHECK: ![[LOC]] = !MDLocation(line: 4, scope: +;CHECK: ![[LOC2]] = !MDLocation(line: 7, scope: define i32 @depth(double* nocapture %A, i32 %m) #0 { entry: - tail call void @llvm.dbg.value(metadata !{double* %A}, i64 0, metadata !12), !dbg !19 - tail call void @llvm.dbg.value(metadata !{i32 %m}, i64 0, metadata !13), !dbg !19 - tail call void @llvm.dbg.value(metadata !20, i64 0, metadata !14), !dbg !21 - tail call void @llvm.dbg.value(metadata !22, i64 0, metadata !15), !dbg !21 - tail call void @llvm.dbg.value(metadata !2, i64 0, metadata !16), !dbg !23 + tail call void @llvm.dbg.value(metadata double* %A, i64 0, metadata !12, metadata !{}), !dbg !19 + tail call void @llvm.dbg.value(metadata i32 %m, i64 0, metadata !13, metadata !{}), !dbg !19 + tail call void @llvm.dbg.value(metadata i32 00, i64 0, metadata !14, metadata !{}), !dbg !21 + tail call void @llvm.dbg.value(metadata i32 02, i64 0, metadata !15, metadata !{}), !dbg !21 + tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !16, metadata !{}), !dbg !23 %cmp8 = icmp sgt i32 %m, 0, !dbg !23 br i1 %cmp8, label %for.body.lr.ph, label %for.end, !dbg !23 @@ -49,7 +49,7 @@ for.end: ; preds = %for.body.lr.ph, %en } ; Function Attrs: nounwind readnone -declare void @llvm.dbg.value(metadata, i64, metadata) #1 +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1 attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone } @@ -57,33 +57,33 @@ attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!18, !32} -!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.4 (trunk 187335) (llvm/trunk 187335:187340M)", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/Users/nadav/file.c] [DW_LANG_C99] -!1 = metadata !{metadata !"file.c", metadata !"/Users/nadav"} -!2 = metadata !{i32 0} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"depth", metadata !"depth", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i32 (double*, i32)* @depth, null, null, metadata !11, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [depth] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/Users/nadav/file.c] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{metadata !8, metadata !9, metadata !8} -!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] -!9 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !10} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from double] -!10 = metadata !{i32 786468, null, null, metadata !"double", i32 0, i64 64, i64 64, i64 0, i32 0, i32 4} ; [ DW_TAG_base_type ] [double] [line 0, size 64, align 64, offset 0, enc DW_ATE_float] -!11 = metadata !{metadata !12, metadata !13, metadata !14, metadata !15, metadata !16} -!12 = metadata !{i32 786689, metadata !4, metadata !"A", metadata !5, i32 16777217, metadata !9, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [A] [line 1] -!13 = metadata !{i32 786689, metadata !4, metadata !"m", metadata !5, i32 33554433, metadata !8, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [m] [line 1] -!14 = metadata !{i32 786688, metadata !4, metadata !"y0", metadata !5, i32 2, metadata !10, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [y0] [line 2] -!15 = metadata !{i32 786688, metadata !4, metadata !"y1", metadata !5, i32 2, metadata !10, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [y1] [line 2] -!16 = metadata !{i32 786688, metadata !17, metadata !"i", metadata !5, i32 3, metadata !8, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [i] [line 3] -!17 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [/Users/nadav/file.c] -!18 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} -!19 = metadata !{i32 1, i32 0, metadata !4, null} -!20 = metadata !{double 0.000000e+00} -!21 = metadata !{i32 2, i32 0, metadata !4, null} -!22 = metadata !{double 1.000000e+00} -!23 = metadata !{i32 3, i32 0, metadata !17, null} -!24 = metadata !{i32 4, i32 0, metadata !25, null} -!25 = metadata !{i32 786443, metadata !1, metadata !17, i32 3, i32 0, i32 1} ; [ DW_TAG_lexical_block ] [/Users/nadav/file.c] -!29 = metadata !{i32 5, i32 0, metadata !25, null} -!30 = metadata !{i32 7, i32 0, metadata !4, null} -!31 = metadata !{i32 8, i32 0, metadata !4, null} ; [ DW_TAG_imported_declaration ] -!32 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x11\0012\00clang version 3.4 (trunk 187335) (llvm/trunk 187335:187340M)\001\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [/Users/nadav/file.c] [DW_LANG_C99] +!1 = !{!"file.c", !"/Users/nadav"} +!2 = !{i32 0} +!3 = !{!4} +!4 = !{!"0x2e\00depth\00depth\00\001\000\001\000\006\00256\001\001", !1, !5, !6, null, i32 (double*, i32)* @depth, null, null, !11} ; [ DW_TAG_subprogram ] [line 1] [def] [depth] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [/Users/nadav/file.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{!8, !9, !8} +!8 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!9 = !{!"0xf\00\000\0064\0064\000\000", null, null, !10} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from double] +!10 = !{!"0x24\00double\000\0064\0064\000\000\004", null, null} ; [ DW_TAG_base_type ] [double] [line 0, size 64, align 64, offset 0, enc DW_ATE_float] +!11 = !{!12, !13, !14, !15, !16} +!12 = !{!"0x101\00A\0016777217\000", !4, !5, !9} ; [ DW_TAG_arg_variable ] [A] [line 1] +!13 = !{!"0x101\00m\0033554433\000", !4, !5, !8} ; [ DW_TAG_arg_variable ] [m] [line 1] +!14 = !{!"0x100\00y0\002\000", !4, !5, !10} ; [ DW_TAG_auto_variable ] [y0] [line 2] +!15 = !{!"0x100\00y1\002\000", !4, !5, !10} ; [ DW_TAG_auto_variable ] [y1] [line 2] +!16 = !{!"0x100\00i\003\000", !17, !5, !8} ; [ DW_TAG_auto_variable ] [i] [line 3] +!17 = !{!"0xb\003\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [/Users/nadav/file.c] +!18 = !{i32 2, !"Dwarf Version", i32 2} +!19 = !MDLocation(line: 1, scope: !4) +!20 = !{double 0.000000e+00} +!21 = !MDLocation(line: 2, scope: !4) +!22 = !{double 1.000000e+00} +!23 = !MDLocation(line: 3, scope: !17) +!24 = !MDLocation(line: 4, scope: !25) +!25 = !{!"0xb\003\000\001", !1, !17} ; [ DW_TAG_lexical_block ] [/Users/nadav/file.c] +!29 = !MDLocation(line: 5, scope: !25) +!30 = !MDLocation(line: 7, scope: !4) +!31 = !MDLocation(line: 8, scope: !4) +!32 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/SLPVectorizer/X86/extract_in_tree_user.ll b/test/Transforms/SLPVectorizer/X86/extract_in_tree_user.ll new file mode 100644 index 000000000000..3628042cdb4d --- /dev/null +++ b/test/Transforms/SLPVectorizer/X86/extract_in_tree_user.ll @@ -0,0 +1,70 @@ +; RUN: opt < %s -basicaa -slp-vectorizer -S -mtriple=i386-apple-macosx10.9.0 -mcpu=corei7-avx | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +@a = common global i64* null, align 8 + +; Function Attrs: nounwind ssp uwtable +define i32 @fn1() { +entry: + %0 = load i64** @a, align 8 + %add.ptr = getelementptr inbounds i64* %0, i64 11 + %1 = ptrtoint i64* %add.ptr to i64 + store i64 %1, i64* %add.ptr, align 8 + %add.ptr1 = getelementptr inbounds i64* %0, i64 56 + %2 = ptrtoint i64* %add.ptr1 to i64 + %arrayidx2 = getelementptr inbounds i64* %0, i64 12 + store i64 %2, i64* %arrayidx2, align 8 + ret i32 undef +; CHECK-LABEL: @fn1( +; CHECK: extractelement <2 x i64*> +; CHECK: ret +} + + +declare float @llvm.powi.f32(float, i32) +define void @fn2(i32* %a, i32* %b, float* %c) { +entry: + %i0 = load i32* %a, align 4 + %i1 = load i32* %b, align 4 + %add1 = add i32 %i0, %i1 + %fp1 = sitofp i32 %add1 to float + %call1 = tail call float @llvm.powi.f32(float %fp1,i32 %add1) nounwind readnone + + %arrayidx2 = getelementptr inbounds i32* %a, i32 1 + %i2 = load i32* %arrayidx2, align 4 + %arrayidx3 = getelementptr inbounds i32* %b, i32 1 + %i3 = load i32* %arrayidx3, align 4 + %add2 = add i32 %i2, %i3 + %fp2 = sitofp i32 %add2 to float + %call2 = tail call float @llvm.powi.f32(float %fp2,i32 %add1) nounwind readnone + + %arrayidx4 = getelementptr inbounds i32* %a, i32 2 + %i4 = load i32* %arrayidx4, align 4 + %arrayidx5 = getelementptr inbounds i32* %b, i32 2 + %i5 = load i32* %arrayidx5, align 4 + %add3 = add i32 %i4, %i5 + %fp3 = sitofp i32 %add3 to float + %call3 = tail call float @llvm.powi.f32(float %fp3,i32 %add1) nounwind readnone + + %arrayidx6 = getelementptr inbounds i32* %a, i32 3 + %i6 = load i32* %arrayidx6, align 4 + %arrayidx7 = getelementptr inbounds i32* %b, i32 3 + %i7 = load i32* %arrayidx7, align 4 + %add4 = add i32 %i6, %i7 + %fp4 = sitofp i32 %add4 to float + %call4 = tail call float @llvm.powi.f32(float %fp4,i32 %add1) nounwind readnone + + store float %call1, float* %c, align 4 + %arrayidx8 = getelementptr inbounds float* %c, i32 1 + store float %call2, float* %arrayidx8, align 4 + %arrayidx9 = getelementptr inbounds float* %c, i32 2 + store float %call3, float* %arrayidx9, align 4 + %arrayidx10 = getelementptr inbounds float* %c, i32 3 + store float %call4, float* %arrayidx10, align 4 + ret void + +; CHECK-LABEL: @fn2( +; CHECK: extractelement <4 x i32> +; CHECK: ret +} diff --git a/test/Transforms/SLPVectorizer/X86/hoist.ll b/test/Transforms/SLPVectorizer/X86/hoist.ll index 5074ceaaabd7..78c58f1d84e9 100644 --- a/test/Transforms/SLPVectorizer/X86/hoist.ll +++ b/test/Transforms/SLPVectorizer/X86/hoist.ll @@ -21,7 +21,7 @@ target triple = "i386-apple-macosx10.9.0" ; loop body: ;CHECK: phi ;CHECK: load <4 x i32> -;CHECK: add <4 x i32> +;CHECK: add nsw <4 x i32> ;CHECK: store <4 x i32> ;CHECK: ret define i32 @foo(i32* nocapture %A, i32 %n, i32 %k) { diff --git a/test/Transforms/SLPVectorizer/X86/horizontal.ll b/test/Transforms/SLPVectorizer/X86/horizontal.ll index 8f919512ff8d..18360471c190 100644 --- a/test/Transforms/SLPVectorizer/X86/horizontal.ll +++ b/test/Transforms/SLPVectorizer/X86/horizontal.ll @@ -148,7 +148,7 @@ for.end: ; } ; CHECK-LABEL: long_red -; CHECK: fmul <4 x float> +; CHECK: fmul fast <4 x float> ; CHECK: shufflevector <4 x float> define i32 @long_red(float* noalias %A, float* noalias %B, i32 %n) { @@ -250,7 +250,7 @@ for.end: ; } ; CHECK-LABEL: chain_red -; CHECK: fmul <4 x float> +; CHECK: fmul fast <4 x float> ; CHECK: shufflevector <4 x float> define i32 @chain_red(float* noalias %A, float* noalias %B, i32 %n) { @@ -317,7 +317,7 @@ for.end: ; } ; CHECK-LABEL: store_red -; CHECK: fmul <4 x float> +; CHECK: fmul fast <4 x float> ; CHECK: shufflevector <4 x float> define i32 @store_red(float* noalias %A, float* noalias %B, float* noalias %C, i32 %n) { @@ -379,7 +379,7 @@ for.end: ; } ; STORE-LABEL: store_red_double -; STORE: fmul <2 x double> +; STORE: fmul fast <2 x double> ; STORE: extractelement <2 x double> ; STORE: extractelement <2 x double> diff --git a/test/Transforms/SLPVectorizer/X86/in-tree-user.ll b/test/Transforms/SLPVectorizer/X86/in-tree-user.ll index 3115232887bd..194a0fbd5ed0 100644 --- a/test/Transforms/SLPVectorizer/X86/in-tree-user.ll +++ b/test/Transforms/SLPVectorizer/X86/in-tree-user.ll @@ -5,9 +5,11 @@ target triple = "x86_64-apple-macosx10.7.0" @.str = private unnamed_addr constant [6 x i8] c"bingo\00", align 1 -; We can't vectorize when the roots are used inside the tree. +; Uses inside the tree must be scheduled after the corresponding tree bundle. ;CHECK-LABEL: @in_tree_user( -;CHECK-NOT: load <2 x double> +;CHECK: load <2 x double> +;CHECK: fadd <2 x double> +;CHECK: InTreeUser = fadd ;CHECK: ret define void @in_tree_user(double* nocapture %A, i32 %n) { entry: @@ -22,7 +24,7 @@ for.body: ; preds = %for.inc, %entry %mul1 = fmul double %conv, %1 %mul2 = fmul double %mul1, 7.000000e+00 %add = fadd double %mul2, 5.000000e+00 - %BadValue = fadd double %add, %add ; <------------------ In tree user. + %InTreeUser = fadd double %add, %add ; <------------------ In tree user. %2 = or i64 %0, 1 %arrayidx6 = getelementptr inbounds double* %A, i64 %2 %3 = load double* %arrayidx6, align 8 @@ -43,6 +45,7 @@ for.inc: ; preds = %for.body, %if.then br i1 %exitcond, label %for.end, label %for.body for.end: ; preds = %for.inc + store double %InTreeUser, double* %A, align 8 ; Avoid dead code elimination of the InTreeUser. ret void } diff --git a/test/Transforms/SLPVectorizer/X86/insert-element-build-vector.ll b/test/Transforms/SLPVectorizer/X86/insert-element-build-vector.ll index 9eda29f101ac..0221613b9707 100644 --- a/test/Transforms/SLPVectorizer/X86/insert-element-build-vector.ll +++ b/test/Transforms/SLPVectorizer/X86/insert-element-build-vector.ll @@ -35,6 +35,49 @@ define <4 x float> @simple_select(<4 x float> %a, <4 x float> %b, <4 x i32> %c) ret <4 x float> %rd } +declare void @llvm.assume(i1) nounwind + +; This entire tree is ephemeral, don't vectorize any of it. +define <4 x float> @simple_select_eph(<4 x float> %a, <4 x float> %b, <4 x i32> %c) #0 { +; CHECK-LABEL: @simple_select_eph( +; CHECK-NOT: icmp ne <4 x i32> +; CHECK-NOT: select <4 x i1> + %c0 = extractelement <4 x i32> %c, i32 0 + %c1 = extractelement <4 x i32> %c, i32 1 + %c2 = extractelement <4 x i32> %c, i32 2 + %c3 = extractelement <4 x i32> %c, i32 3 + %a0 = extractelement <4 x float> %a, i32 0 + %a1 = extractelement <4 x float> %a, i32 1 + %a2 = extractelement <4 x float> %a, i32 2 + %a3 = extractelement <4 x float> %a, i32 3 + %b0 = extractelement <4 x float> %b, i32 0 + %b1 = extractelement <4 x float> %b, i32 1 + %b2 = extractelement <4 x float> %b, i32 2 + %b3 = extractelement <4 x float> %b, i32 3 + %cmp0 = icmp ne i32 %c0, 0 + %cmp1 = icmp ne i32 %c1, 0 + %cmp2 = icmp ne i32 %c2, 0 + %cmp3 = icmp ne i32 %c3, 0 + %s0 = select i1 %cmp0, float %a0, float %b0 + %s1 = select i1 %cmp1, float %a1, float %b1 + %s2 = select i1 %cmp2, float %a2, float %b2 + %s3 = select i1 %cmp3, float %a3, float %b3 + %ra = insertelement <4 x float> undef, float %s0, i32 0 + %rb = insertelement <4 x float> %ra, float %s1, i32 1 + %rc = insertelement <4 x float> %rb, float %s2, i32 2 + %rd = insertelement <4 x float> %rc, float %s3, i32 3 + %q0 = extractelement <4 x float> %rd, i32 0 + %q1 = extractelement <4 x float> %rd, i32 1 + %q2 = extractelement <4 x float> %rd, i32 2 + %q3 = extractelement <4 x float> %rd, i32 3 + %q4 = fadd float %q0, %q1 + %q5 = fadd float %q2, %q3 + %q6 = fadd float %q4, %q5 + %qi = fcmp olt float %q6, %q5 + call void @llvm.assume(i1 %qi) + ret <4 x float> undef +} + ; Insert in an order different from the vector indices to make sure it ; doesn't matter define <4 x float> @simple_select_insert_out_of_order(<4 x float> %a, <4 x float> %b, <4 x i32> %c) #0 { diff --git a/test/Transforms/SLPVectorizer/X86/loopinvariant.ll b/test/Transforms/SLPVectorizer/X86/loopinvariant.ll index aef2479dd524..bc12926e3fe6 100644 --- a/test/Transforms/SLPVectorizer/X86/loopinvariant.ll +++ b/test/Transforms/SLPVectorizer/X86/loopinvariant.ll @@ -5,10 +5,10 @@ target triple = "x86_64-apple-macosx10.8.0" ;CHECK-LABEL: @foo( ;CHECK: load <4 x i32> -;CHECK: add <4 x i32> +;CHECK: add nsw <4 x i32> ;CHECK: store <4 x i32> ;CHECK: load <4 x i32> -;CHECK: add <4 x i32> +;CHECK: add nsw <4 x i32> ;CHECK: store <4 x i32> ;CHECK: ret define i32 @foo(i32* nocapture %A, i32 %n) #0 { diff --git a/test/Transforms/SLPVectorizer/X86/metadata.ll b/test/Transforms/SLPVectorizer/X86/metadata.ll index 5bd2fa4ea684..e021cca23e34 100644 --- a/test/Transforms/SLPVectorizer/X86/metadata.ll +++ b/test/Transforms/SLPVectorizer/X86/metadata.ll @@ -51,11 +51,11 @@ entry: ret void } -;CHECK-DAG: ![[TBAA]] = metadata !{metadata [[TYPEC:!.*]], metadata [[TYPEC]], i64 0} -;CHECK-DAG: ![[FP1]] = metadata !{float 5.000000e+00} -;CHECK-DAG: ![[FP2]] = metadata !{float 2.500000e+00} -!0 = metadata !{ float 5.0 } -!1 = metadata !{ float 2.5 } -!2 = metadata !{metadata !"Simple C/C++ TBAA"} -!3 = metadata !{metadata !"omnipotent char", metadata !2} -!4 = metadata !{metadata !"double", metadata !3} +;CHECK-DAG: ![[TBAA]] = !{[[TYPEC:!.*]], [[TYPEC]], i64 0} +;CHECK-DAG: ![[FP1]] = !{float 5.000000e+00} +;CHECK-DAG: ![[FP2]] = !{float 2.500000e+00} +!0 = !{ float 5.0 } +!1 = !{ float 2.5 } +!2 = !{!"Simple C/C++ TBAA"} +!3 = !{!"omnipotent char", !2} +!4 = !{!"double", !3} diff --git a/test/Transforms/SLPVectorizer/X86/multi_user.ll b/test/Transforms/SLPVectorizer/X86/multi_user.ll index cab99945e29e..63a77e4b6733 100644 --- a/test/Transforms/SLPVectorizer/X86/multi_user.ll +++ b/test/Transforms/SLPVectorizer/X86/multi_user.ll @@ -14,7 +14,7 @@ target triple = "x86_64-apple-macosx10.7.0" ;CHECK-LABEL: @foo( ;CHECK: insertelement <4 x i32> ;CHECK: load <4 x i32> -;CHECK: add <4 x i32> +;CHECK: add nsw <4 x i32> ;CHECK: store <4 x i32> ;CHECK: ret define i32 @foo(i32* nocapture %A, i32 %n) { diff --git a/test/Transforms/SLPVectorizer/X86/powof2div.ll b/test/Transforms/SLPVectorizer/X86/powof2div.ll new file mode 100644 index 000000000000..7aa1efde6f06 --- /dev/null +++ b/test/Transforms/SLPVectorizer/X86/powof2div.ll @@ -0,0 +1,43 @@ +; RUN: opt < %s -basicaa -slp-vectorizer -S -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7-avx | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +;CHECK-LABEL: @powof2div( +;CHECK: load <4 x i32>* +;CHECK: add nsw <4 x i32> +;CHECK: sdiv <4 x i32> +define void @powof2div(i32* noalias nocapture %a, i32* noalias nocapture readonly %b, i32* noalias nocapture readonly %c){ +entry: + %0 = load i32* %b, align 4 + %1 = load i32* %c, align 4 + %add = add nsw i32 %1, %0 + %div = sdiv i32 %add, 2 + store i32 %div, i32* %a, align 4 + %arrayidx3 = getelementptr inbounds i32* %b, i64 1 + %2 = load i32* %arrayidx3, align 4 + %arrayidx4 = getelementptr inbounds i32* %c, i64 1 + %3 = load i32* %arrayidx4, align 4 + %add5 = add nsw i32 %3, %2 + %div6 = sdiv i32 %add5, 2 + %arrayidx7 = getelementptr inbounds i32* %a, i64 1 + store i32 %div6, i32* %arrayidx7, align 4 + %arrayidx8 = getelementptr inbounds i32* %b, i64 2 + %4 = load i32* %arrayidx8, align 4 + %arrayidx9 = getelementptr inbounds i32* %c, i64 2 + %5 = load i32* %arrayidx9, align 4 + %add10 = add nsw i32 %5, %4 + %div11 = sdiv i32 %add10, 2 + %arrayidx12 = getelementptr inbounds i32* %a, i64 2 + store i32 %div11, i32* %arrayidx12, align 4 + %arrayidx13 = getelementptr inbounds i32* %b, i64 3 + %6 = load i32* %arrayidx13, align 4 + %arrayidx14 = getelementptr inbounds i32* %c, i64 3 + %7 = load i32* %arrayidx14, align 4 + %add15 = add nsw i32 %7, %6 + %div16 = sdiv i32 %add15, 2 + %arrayidx17 = getelementptr inbounds i32* %a, i64 3 + store i32 %div16, i32* %arrayidx17, align 4 + ret void +} + diff --git a/test/Transforms/SLPVectorizer/X86/pr16899.ll b/test/Transforms/SLPVectorizer/X86/pr16899.ll index 8631bc9125df..c642f3cfe1d4 100644 --- a/test/Transforms/SLPVectorizer/X86/pr16899.ll +++ b/test/Transforms/SLPVectorizer/X86/pr16899.ll @@ -23,9 +23,9 @@ do.body: ; preds = %do.body, %entry attributes #0 = { noreturn nounwind readonly "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -!0 = metadata !{metadata !"any pointer", metadata !1} -!1 = metadata !{metadata !"omnipotent char", metadata !2} -!2 = metadata !{metadata !"Simple C/C++ TBAA"} -!3 = metadata !{metadata !"int", metadata !1} -!4 = metadata !{metadata !0, metadata !0, i64 0} -!5 = metadata !{metadata !3, metadata !3, i64 0} +!0 = !{!"any pointer", !1} +!1 = !{!"omnipotent char", !2} +!2 = !{!"Simple C/C++ TBAA"} +!3 = !{!"int", !1} +!4 = !{!0, !0, i64 0} +!5 = !{!3, !3, i64 0} diff --git a/test/Transforms/SLPVectorizer/X86/propagate_ir_flags.ll b/test/Transforms/SLPVectorizer/X86/propagate_ir_flags.ll new file mode 100644 index 000000000000..3843ef7f62c7 --- /dev/null +++ b/test/Transforms/SLPVectorizer/X86/propagate_ir_flags.ll @@ -0,0 +1,350 @@ +; RUN: opt < %s -basicaa -slp-vectorizer -S | FileCheck %s + +; Check propagation of optional IR flags (PR20802). For a flag to +; propagate from scalar instructions to their vector replacement, +; *all* scalar instructions must have the flag. + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-unknown" + +; CHECK-LABEL: @exact( +; CHECK: lshr exact <4 x i32> +define void @exact(i32* %x) { + %idx1 = getelementptr inbounds i32* %x, i64 0 + %idx2 = getelementptr inbounds i32* %x, i64 1 + %idx3 = getelementptr inbounds i32* %x, i64 2 + %idx4 = getelementptr inbounds i32* %x, i64 3 + + %load1 = load i32* %idx1, align 4 + %load2 = load i32* %idx2, align 4 + %load3 = load i32* %idx3, align 4 + %load4 = load i32* %idx4, align 4 + + %op1 = lshr exact i32 %load1, 1 + %op2 = lshr exact i32 %load2, 1 + %op3 = lshr exact i32 %load3, 1 + %op4 = lshr exact i32 %load4, 1 + + store i32 %op1, i32* %idx1, align 4 + store i32 %op2, i32* %idx2, align 4 + store i32 %op3, i32* %idx3, align 4 + store i32 %op4, i32* %idx4, align 4 + + ret void +} + +; CHECK-LABEL: @not_exact( +; CHECK: lshr <4 x i32> +define void @not_exact(i32* %x) { + %idx1 = getelementptr inbounds i32* %x, i64 0 + %idx2 = getelementptr inbounds i32* %x, i64 1 + %idx3 = getelementptr inbounds i32* %x, i64 2 + %idx4 = getelementptr inbounds i32* %x, i64 3 + + %load1 = load i32* %idx1, align 4 + %load2 = load i32* %idx2, align 4 + %load3 = load i32* %idx3, align 4 + %load4 = load i32* %idx4, align 4 + + %op1 = lshr exact i32 %load1, 1 + %op2 = lshr i32 %load2, 1 + %op3 = lshr exact i32 %load3, 1 + %op4 = lshr exact i32 %load4, 1 + + store i32 %op1, i32* %idx1, align 4 + store i32 %op2, i32* %idx2, align 4 + store i32 %op3, i32* %idx3, align 4 + store i32 %op4, i32* %idx4, align 4 + + ret void +} + +; CHECK-LABEL: @nsw( +; CHECK: add nsw <4 x i32> +define void @nsw(i32* %x) { + %idx1 = getelementptr inbounds i32* %x, i64 0 + %idx2 = getelementptr inbounds i32* %x, i64 1 + %idx3 = getelementptr inbounds i32* %x, i64 2 + %idx4 = getelementptr inbounds i32* %x, i64 3 + + %load1 = load i32* %idx1, align 4 + %load2 = load i32* %idx2, align 4 + %load3 = load i32* %idx3, align 4 + %load4 = load i32* %idx4, align 4 + + %op1 = add nsw i32 %load1, 1 + %op2 = add nsw i32 %load2, 1 + %op3 = add nsw i32 %load3, 1 + %op4 = add nsw i32 %load4, 1 + + store i32 %op1, i32* %idx1, align 4 + store i32 %op2, i32* %idx2, align 4 + store i32 %op3, i32* %idx3, align 4 + store i32 %op4, i32* %idx4, align 4 + + ret void +} + +; CHECK-LABEL: @not_nsw( +; CHECK: add <4 x i32> +define void @not_nsw(i32* %x) { + %idx1 = getelementptr inbounds i32* %x, i64 0 + %idx2 = getelementptr inbounds i32* %x, i64 1 + %idx3 = getelementptr inbounds i32* %x, i64 2 + %idx4 = getelementptr inbounds i32* %x, i64 3 + + %load1 = load i32* %idx1, align 4 + %load2 = load i32* %idx2, align 4 + %load3 = load i32* %idx3, align 4 + %load4 = load i32* %idx4, align 4 + + %op1 = add nsw i32 %load1, 1 + %op2 = add nsw i32 %load2, 1 + %op3 = add nsw i32 %load3, 1 + %op4 = add i32 %load4, 1 + + store i32 %op1, i32* %idx1, align 4 + store i32 %op2, i32* %idx2, align 4 + store i32 %op3, i32* %idx3, align 4 + store i32 %op4, i32* %idx4, align 4 + + ret void +} + +; CHECK-LABEL: @nuw( +; CHECK: add nuw <4 x i32> +define void @nuw(i32* %x) { + %idx1 = getelementptr inbounds i32* %x, i64 0 + %idx2 = getelementptr inbounds i32* %x, i64 1 + %idx3 = getelementptr inbounds i32* %x, i64 2 + %idx4 = getelementptr inbounds i32* %x, i64 3 + + %load1 = load i32* %idx1, align 4 + %load2 = load i32* %idx2, align 4 + %load3 = load i32* %idx3, align 4 + %load4 = load i32* %idx4, align 4 + + %op1 = add nuw i32 %load1, 1 + %op2 = add nuw i32 %load2, 1 + %op3 = add nuw i32 %load3, 1 + %op4 = add nuw i32 %load4, 1 + + store i32 %op1, i32* %idx1, align 4 + store i32 %op2, i32* %idx2, align 4 + store i32 %op3, i32* %idx3, align 4 + store i32 %op4, i32* %idx4, align 4 + + ret void +} + +; CHECK-LABEL: @not_nuw( +; CHECK: add <4 x i32> +define void @not_nuw(i32* %x) { + %idx1 = getelementptr inbounds i32* %x, i64 0 + %idx2 = getelementptr inbounds i32* %x, i64 1 + %idx3 = getelementptr inbounds i32* %x, i64 2 + %idx4 = getelementptr inbounds i32* %x, i64 3 + + %load1 = load i32* %idx1, align 4 + %load2 = load i32* %idx2, align 4 + %load3 = load i32* %idx3, align 4 + %load4 = load i32* %idx4, align 4 + + %op1 = add nuw i32 %load1, 1 + %op2 = add i32 %load2, 1 + %op3 = add i32 %load3, 1 + %op4 = add nuw i32 %load4, 1 + + store i32 %op1, i32* %idx1, align 4 + store i32 %op2, i32* %idx2, align 4 + store i32 %op3, i32* %idx3, align 4 + store i32 %op4, i32* %idx4, align 4 + + ret void +} + +; CHECK-LABEL: @nnan( +; CHECK: fadd nnan <4 x float> +define void @nnan(float* %x) { + %idx1 = getelementptr inbounds float* %x, i64 0 + %idx2 = getelementptr inbounds float* %x, i64 1 + %idx3 = getelementptr inbounds float* %x, i64 2 + %idx4 = getelementptr inbounds float* %x, i64 3 + + %load1 = load float* %idx1, align 4 + %load2 = load float* %idx2, align 4 + %load3 = load float* %idx3, align 4 + %load4 = load float* %idx4, align 4 + + %op1 = fadd fast nnan float %load1, 1.0 + %op2 = fadd nnan ninf float %load2, 1.0 + %op3 = fadd nsz nnan float %load3, 1.0 + %op4 = fadd arcp nnan float %load4, 1.0 + + store float %op1, float* %idx1, align 4 + store float %op2, float* %idx2, align 4 + store float %op3, float* %idx3, align 4 + store float %op4, float* %idx4, align 4 + + ret void +} + +; CHECK-LABEL: @not_nnan( +; CHECK: fadd <4 x float> +define void @not_nnan(float* %x) { + %idx1 = getelementptr inbounds float* %x, i64 0 + %idx2 = getelementptr inbounds float* %x, i64 1 + %idx3 = getelementptr inbounds float* %x, i64 2 + %idx4 = getelementptr inbounds float* %x, i64 3 + + %load1 = load float* %idx1, align 4 + %load2 = load float* %idx2, align 4 + %load3 = load float* %idx3, align 4 + %load4 = load float* %idx4, align 4 + + %op1 = fadd nnan float %load1, 1.0 + %op2 = fadd ninf float %load2, 1.0 + %op3 = fadd nsz float %load3, 1.0 + %op4 = fadd arcp float %load4, 1.0 + + store float %op1, float* %idx1, align 4 + store float %op2, float* %idx2, align 4 + store float %op3, float* %idx3, align 4 + store float %op4, float* %idx4, align 4 + + ret void +} + +; CHECK-LABEL: @only_fast( +; CHECK: fadd fast <4 x float> +define void @only_fast(float* %x) { + %idx1 = getelementptr inbounds float* %x, i64 0 + %idx2 = getelementptr inbounds float* %x, i64 1 + %idx3 = getelementptr inbounds float* %x, i64 2 + %idx4 = getelementptr inbounds float* %x, i64 3 + + %load1 = load float* %idx1, align 4 + %load2 = load float* %idx2, align 4 + %load3 = load float* %idx3, align 4 + %load4 = load float* %idx4, align 4 + + %op1 = fadd fast nnan float %load1, 1.0 + %op2 = fadd fast nnan ninf float %load2, 1.0 + %op3 = fadd fast nsz nnan float %load3, 1.0 + %op4 = fadd arcp nnan fast float %load4, 1.0 + + store float %op1, float* %idx1, align 4 + store float %op2, float* %idx2, align 4 + store float %op3, float* %idx3, align 4 + store float %op4, float* %idx4, align 4 + + ret void +} + +; CHECK-LABEL: @only_arcp( +; CHECK: fadd arcp <4 x float> +define void @only_arcp(float* %x) { + %idx1 = getelementptr inbounds float* %x, i64 0 + %idx2 = getelementptr inbounds float* %x, i64 1 + %idx3 = getelementptr inbounds float* %x, i64 2 + %idx4 = getelementptr inbounds float* %x, i64 3 + + %load1 = load float* %idx1, align 4 + %load2 = load float* %idx2, align 4 + %load3 = load float* %idx3, align 4 + %load4 = load float* %idx4, align 4 + + %op1 = fadd fast float %load1, 1.0 + %op2 = fadd fast float %load2, 1.0 + %op3 = fadd fast float %load3, 1.0 + %op4 = fadd arcp float %load4, 1.0 + + store float %op1, float* %idx1, align 4 + store float %op2, float* %idx2, align 4 + store float %op3, float* %idx3, align 4 + store float %op4, float* %idx4, align 4 + + ret void +} + +; CHECK-LABEL: @addsub_all_nsw +; CHECK: add nsw <4 x i32> +; CHECK: sub nsw <4 x i32> +define void @addsub_all_nsw(i32* %x) { + %idx1 = getelementptr inbounds i32* %x, i64 0 + %idx2 = getelementptr inbounds i32* %x, i64 1 + %idx3 = getelementptr inbounds i32* %x, i64 2 + %idx4 = getelementptr inbounds i32* %x, i64 3 + + %load1 = load i32* %idx1, align 4 + %load2 = load i32* %idx2, align 4 + %load3 = load i32* %idx3, align 4 + %load4 = load i32* %idx4, align 4 + + %op1 = add nsw i32 %load1, 1 + %op2 = sub nsw i32 %load2, 1 + %op3 = add nsw i32 %load3, 1 + %op4 = sub nsw i32 %load4, 1 + + store i32 %op1, i32* %idx1, align 4 + store i32 %op2, i32* %idx2, align 4 + store i32 %op3, i32* %idx3, align 4 + store i32 %op4, i32* %idx4, align 4 + + ret void +} + +; CHECK-LABEL: @addsub_some_nsw +; CHECK: add nsw <4 x i32> +; CHECK: sub <4 x i32> +define void @addsub_some_nsw(i32* %x) { + %idx1 = getelementptr inbounds i32* %x, i64 0 + %idx2 = getelementptr inbounds i32* %x, i64 1 + %idx3 = getelementptr inbounds i32* %x, i64 2 + %idx4 = getelementptr inbounds i32* %x, i64 3 + + %load1 = load i32* %idx1, align 4 + %load2 = load i32* %idx2, align 4 + %load3 = load i32* %idx3, align 4 + %load4 = load i32* %idx4, align 4 + + %op1 = add nsw i32 %load1, 1 + %op2 = sub nsw i32 %load2, 1 + %op3 = add nsw i32 %load3, 1 + %op4 = sub i32 %load4, 1 + + store i32 %op1, i32* %idx1, align 4 + store i32 %op2, i32* %idx2, align 4 + store i32 %op3, i32* %idx3, align 4 + store i32 %op4, i32* %idx4, align 4 + + ret void +} + +; CHECK-LABEL: @addsub_no_nsw +; CHECK: add <4 x i32> +; CHECK: sub <4 x i32> +define void @addsub_no_nsw(i32* %x) { + %idx1 = getelementptr inbounds i32* %x, i64 0 + %idx2 = getelementptr inbounds i32* %x, i64 1 + %idx3 = getelementptr inbounds i32* %x, i64 2 + %idx4 = getelementptr inbounds i32* %x, i64 3 + + %load1 = load i32* %idx1, align 4 + %load2 = load i32* %idx2, align 4 + %load3 = load i32* %idx3, align 4 + %load4 = load i32* %idx4, align 4 + + %op1 = add i32 %load1, 1 + %op2 = sub nsw i32 %load2, 1 + %op3 = add nsw i32 %load3, 1 + %op4 = sub i32 %load4, 1 + + store i32 %op1, i32* %idx1, align 4 + store i32 %op2, i32* %idx2, align 4 + store i32 %op3, i32* %idx3, align 4 + store i32 %op4, i32* %idx4, align 4 + + ret void +} + diff --git a/test/Transforms/SLPVectorizer/X86/return.ll b/test/Transforms/SLPVectorizer/X86/return.ll new file mode 100644 index 000000000000..1a81c235bdfb --- /dev/null +++ b/test/Transforms/SLPVectorizer/X86/return.ll @@ -0,0 +1,54 @@ +; RUN: opt < %s -basicaa -slp-vectorizer -S | FileCheck %s +target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128" +target triple = "x86_64--linux-gnu" + +@a = common global [4 x double] zeroinitializer, align 8 +@b = common global [4 x double] zeroinitializer, align 8 + +; [4], b[4]; +; double foo() { +; double sum =0; +; sum = (a[0]+b[0]) + (a[1]+b[1]); +; return sum; +; } + +; CHECK-LABEL: @return1 +; CHECK: %0 = load <2 x double>* +; CHECK: %1 = load <2 x double>* +; CHECK: %2 = fadd <2 x double> + +define double @return1() { +entry: + %a0 = load double* getelementptr inbounds ([4 x double]* @a, i32 0, i32 0), align 8 + %b0 = load double* getelementptr inbounds ([4 x double]* @b, i32 0, i32 0), align 8 + %add0 = fadd double %a0, %b0 + %a1 = load double* getelementptr inbounds ([4 x double]* @a, i32 0, i32 1), align 8 + %b1 = load double* getelementptr inbounds ([4 x double]* @b, i32 0, i32 1), align 8 + %add1 = fadd double %a1, %b1 + %add2 = fadd double %add0, %add1 + ret double %add2 +} + +; double hadd(double *x) { +; return ((x[0] + x[2]) + (x[1] + x[3])); +; } + +; CHECK-LABEL: @return2 +; CHECK: %1 = load <2 x double>* +; CHECK: %3 = load <2 x double>* %2 +; CHECK: %4 = fadd <2 x double> %1, %3 + +define double @return2(double* nocapture readonly %x) { +entry: + %x0 = load double* %x, align 4 + %arrayidx1 = getelementptr inbounds double* %x, i32 2 + %x2 = load double* %arrayidx1, align 4 + %add3 = fadd double %x0, %x2 + %arrayidx2 = getelementptr inbounds double* %x, i32 1 + %x1 = load double* %arrayidx2, align 4 + %arrayidx3 = getelementptr inbounds double* %x, i32 3 + %x3 = load double* %arrayidx3, align 4 + %add4 = fadd double %x1, %x3 + %add5 = fadd double %add3, %add4 + ret double %add5 +} diff --git a/test/Transforms/SLPVectorizer/X86/saxpy.ll b/test/Transforms/SLPVectorizer/X86/saxpy.ll index 46263416a90b..4b39d46f89db 100644 --- a/test/Transforms/SLPVectorizer/X86/saxpy.ll +++ b/test/Transforms/SLPVectorizer/X86/saxpy.ll @@ -5,7 +5,7 @@ target triple = "x86_64-apple-macosx10.8.0" ; SLP vectorization example from http://cs.stanford.edu/people/eschkufz/research/asplos291-schkufza.pdf ;CHECK: SAXPY -;CHECK: mul <4 x i32> +;CHECK: mul nsw <4 x i32> ;CHECK: ret define void @SAXPY(i32* noalias nocapture %x, i32* noalias nocapture %y, i32 %a, i64 %i) { diff --git a/test/Transforms/SLPVectorizer/X86/scheduling.ll b/test/Transforms/SLPVectorizer/X86/scheduling.ll new file mode 100644 index 000000000000..3b3bd804e057 --- /dev/null +++ b/test/Transforms/SLPVectorizer/X86/scheduling.ll @@ -0,0 +1,78 @@ +; RUN: opt < %s -basicaa -slp-vectorizer -S -mtriple=i386-apple-macosx10.8.0 -mcpu=corei7-avx | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.9.0" + +;CHECK-LABEL: @foo +;CHECK: load <4 x i32> +;CHECK: load <4 x i32> +;CHECK: %[[S1:.+]] = add nsw <4 x i32> +;CHECK-DAG: store <4 x i32> %[[S1]] +;CHECK-DAG: %[[A1:.+]] = add nsw i32 +;CHECK-DAG: %[[A2:.+]] = add nsw i32 %[[A1]] +;CHECK-DAG: %[[A3:.+]] = add nsw i32 %[[A2]] +;CHECK-DAG: %[[A4:.+]] = add nsw i32 %[[A3]] +;CHECK: ret i32 %[[A4]] + +define i32 @foo(i32* nocapture readonly %diff) #0 { +entry: + %m2 = alloca [8 x [8 x i32]], align 16 + %0 = bitcast [8 x [8 x i32]]* %m2 to i8* + br label %for.body + +for.body: ; preds = %for.body, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %a.088 = phi i32 [ 0, %entry ], [ %add52, %for.body ] + %1 = shl i64 %indvars.iv, 3 + %arrayidx = getelementptr inbounds i32* %diff, i64 %1 + %2 = load i32* %arrayidx, align 4 + %3 = or i64 %1, 4 + %arrayidx2 = getelementptr inbounds i32* %diff, i64 %3 + %4 = load i32* %arrayidx2, align 4 + %add3 = add nsw i32 %4, %2 + %arrayidx6 = getelementptr inbounds [8 x [8 x i32]]* %m2, i64 0, i64 %indvars.iv, i64 0 + store i32 %add3, i32* %arrayidx6, align 16 + %add10 = add nsw i32 %add3, %a.088 + %5 = or i64 %1, 1 + %arrayidx13 = getelementptr inbounds i32* %diff, i64 %5 + %6 = load i32* %arrayidx13, align 4 + %7 = or i64 %1, 5 + %arrayidx16 = getelementptr inbounds i32* %diff, i64 %7 + %8 = load i32* %arrayidx16, align 4 + %add17 = add nsw i32 %8, %6 + %arrayidx20 = getelementptr inbounds [8 x [8 x i32]]* %m2, i64 0, i64 %indvars.iv, i64 1 + store i32 %add17, i32* %arrayidx20, align 4 + %add24 = add nsw i32 %add10, %add17 + %9 = or i64 %1, 2 + %arrayidx27 = getelementptr inbounds i32* %diff, i64 %9 + %10 = load i32* %arrayidx27, align 4 + %11 = or i64 %1, 6 + %arrayidx30 = getelementptr inbounds i32* %diff, i64 %11 + %12 = load i32* %arrayidx30, align 4 + %add31 = add nsw i32 %12, %10 + %arrayidx34 = getelementptr inbounds [8 x [8 x i32]]* %m2, i64 0, i64 %indvars.iv, i64 2 + store i32 %add31, i32* %arrayidx34, align 8 + %add38 = add nsw i32 %add24, %add31 + %13 = or i64 %1, 3 + %arrayidx41 = getelementptr inbounds i32* %diff, i64 %13 + %14 = load i32* %arrayidx41, align 4 + %15 = or i64 %1, 7 + %arrayidx44 = getelementptr inbounds i32* %diff, i64 %15 + %16 = load i32* %arrayidx44, align 4 + %add45 = add nsw i32 %16, %14 + %arrayidx48 = getelementptr inbounds [8 x [8 x i32]]* %m2, i64 0, i64 %indvars.iv, i64 3 + store i32 %add45, i32* %arrayidx48, align 4 + %add52 = add nsw i32 %add38, %add45 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond = icmp eq i64 %indvars.iv.next, 8 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + %arraydecay = getelementptr inbounds [8 x [8 x i32]]* %m2, i64 0, i64 0 + call void @ff([8 x i32]* %arraydecay) #1 + ret i32 %add52 +} + +declare void @ff([8 x i32]*) #2 + + diff --git a/test/Transforms/SLPVectorizer/X86/unreachable.ll b/test/Transforms/SLPVectorizer/X86/unreachable.ll new file mode 100644 index 000000000000..8d609571be17 --- /dev/null +++ b/test/Transforms/SLPVectorizer/X86/unreachable.ll @@ -0,0 +1,40 @@ +; RUN: opt < %s -basicaa -slp-vectorizer -S -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7 + +; Check if the SLPVectorizer does not crash when handling +; unreachable blocks with unscheduleable instructions. + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.9.0" + +define void @foo(i32* nocapture %x) #0 { +entry: + br label %bb2 + +bb1: ; an unreachable block + %t3 = getelementptr inbounds i32* %x, i64 4 + %t4 = load i32* %t3, align 4 + %t5 = getelementptr inbounds i32* %x, i64 5 + %t6 = load i32* %t5, align 4 + %bad = fadd float %bad, 0.000000e+00 ; <- an instruction with self dependency, + ; but legal in unreachable code + %t7 = getelementptr inbounds i32* %x, i64 6 + %t8 = load i32* %t7, align 4 + %t9 = getelementptr inbounds i32* %x, i64 7 + %t10 = load i32* %t9, align 4 + br label %bb2 + +bb2: + %t1.0 = phi i32 [ %t4, %bb1 ], [ 2, %entry ] + %t2.0 = phi i32 [ %t6, %bb1 ], [ 2, %entry ] + %t3.0 = phi i32 [ %t8, %bb1 ], [ 2, %entry ] + %t4.0 = phi i32 [ %t10, %bb1 ], [ 2, %entry ] + store i32 %t1.0, i32* %x, align 4 + %t12 = getelementptr inbounds i32* %x, i64 1 + store i32 %t2.0, i32* %t12, align 4 + %t13 = getelementptr inbounds i32* %x, i64 2 + store i32 %t3.0, i32* %t13, align 4 + %t14 = getelementptr inbounds i32* %x, i64 3 + store i32 %t4.0, i32* %t14, align 4 + ret void +} + diff --git a/test/Transforms/SROA/alignment.ll b/test/Transforms/SROA/alignment.ll index 5fa78766ed0f..4f4e40cf76a7 100644 --- a/test/Transforms/SROA/alignment.ll +++ b/test/Transforms/SROA/alignment.ll @@ -85,15 +85,18 @@ entry: } define void @test5() { -; Test that we preserve underaligned loads and stores when splitting. +; Test that we preserve underaligned loads and stores when splitting. The use +; of volatile in this test case is just to force the loads and stores to not be +; split or promoted out of existence. +; ; CHECK-LABEL: @test5( ; CHECK: alloca [9 x i8] ; CHECK: alloca [9 x i8] ; CHECK: store volatile double 0.0{{.*}}, double* %{{.*}}, align 1 -; CHECK: load i16* %{{.*}}, align 1 +; CHECK: load volatile i16* %{{.*}}, align 1 ; CHECK: load double* %{{.*}}, align 1 ; CHECK: store volatile double %{{.*}}, double* %{{.*}}, align 1 -; CHECK: load i16* %{{.*}}, align 1 +; CHECK: load volatile i16* %{{.*}}, align 1 ; CHECK: ret void entry: @@ -103,7 +106,7 @@ entry: store volatile double 0.0, double* %ptr1, align 1 %weird_gep1 = getelementptr inbounds [18 x i8]* %a, i32 0, i32 7 %weird_cast1 = bitcast i8* %weird_gep1 to i16* - %weird_load1 = load i16* %weird_cast1, align 1 + %weird_load1 = load volatile i16* %weird_cast1, align 1 %raw2 = getelementptr inbounds [18 x i8]* %a, i32 0, i32 9 %ptr2 = bitcast i8* %raw2 to double* @@ -111,7 +114,7 @@ entry: store volatile double %d1, double* %ptr2, align 1 %weird_gep2 = getelementptr inbounds [18 x i8]* %a, i32 0, i32 16 %weird_cast2 = bitcast i8* %weird_gep2 to i16* - %weird_load2 = load i16* %weird_cast2, align 1 + %weird_load2 = load volatile i16* %weird_cast2, align 1 ret void } diff --git a/test/Transforms/SROA/basictest.ll b/test/Transforms/SROA/basictest.ll index dc2b16550a06..e3f762abfa39 100644 --- a/test/Transforms/SROA/basictest.ll +++ b/test/Transforms/SROA/basictest.ll @@ -1440,3 +1440,158 @@ entry: ret void } +define float @test25() { +; Check that we split up stores in order to promote the smaller SSA values.. These types +; of patterns can arise because LLVM maps small memcpy's to integer load and +; stores. If we get a memcpy of an aggregate (such as C and C++ frontends would +; produce, but so might any language frontend), this will in many cases turn into +; an integer load and store. SROA needs to be extremely powerful to correctly +; handle these cases and form splitable and promotable SSA values. +; +; CHECK-LABEL: @test25( +; CHECK-NOT: alloca +; CHECK: %[[F1:.*]] = bitcast i32 0 to float +; CHECK: %[[F2:.*]] = bitcast i32 1065353216 to float +; CHECK: %[[SUM:.*]] = fadd float %[[F1]], %[[F2]] +; CHECK: ret float %[[SUM]] + +entry: + %a = alloca i64 + %b = alloca i64 + %a.cast = bitcast i64* %a to [2 x float]* + %a.gep1 = getelementptr [2 x float]* %a.cast, i32 0, i32 0 + %a.gep2 = getelementptr [2 x float]* %a.cast, i32 0, i32 1 + %b.cast = bitcast i64* %b to [2 x float]* + %b.gep1 = getelementptr [2 x float]* %b.cast, i32 0, i32 0 + %b.gep2 = getelementptr [2 x float]* %b.cast, i32 0, i32 1 + store float 0.0, float* %a.gep1 + store float 1.0, float* %a.gep2 + %v = load i64* %a + store i64 %v, i64* %b + %f1 = load float* %b.gep1 + %f2 = load float* %b.gep2 + %ret = fadd float %f1, %f2 + ret float %ret +} + +@complex1 = external global [2 x float] +@complex2 = external global [2 x float] + +define void @test26() { +; Test a case of splitting up loads and stores against a globals. +; +; CHECK-LABEL: @test26( +; CHECK-NOT: alloca +; CHECK: %[[L1:.*]] = load i32* bitcast +; CHECK: %[[L2:.*]] = load i32* bitcast +; CHECK: %[[F1:.*]] = bitcast i32 %[[L1]] to float +; CHECK: %[[F2:.*]] = bitcast i32 %[[L2]] to float +; CHECK: %[[SUM:.*]] = fadd float %[[F1]], %[[F2]] +; CHECK: %[[C1:.*]] = bitcast float %[[SUM]] to i32 +; CHECK: %[[C2:.*]] = bitcast float %[[SUM]] to i32 +; CHECK: store i32 %[[C1]], i32* bitcast +; CHECK: store i32 %[[C2]], i32* bitcast +; CHECK: ret void + +entry: + %a = alloca i64 + %a.cast = bitcast i64* %a to [2 x float]* + %a.gep1 = getelementptr [2 x float]* %a.cast, i32 0, i32 0 + %a.gep2 = getelementptr [2 x float]* %a.cast, i32 0, i32 1 + %v1 = load i64* bitcast ([2 x float]* @complex1 to i64*) + store i64 %v1, i64* %a + %f1 = load float* %a.gep1 + %f2 = load float* %a.gep2 + %sum = fadd float %f1, %f2 + store float %sum, float* %a.gep1 + store float %sum, float* %a.gep2 + %v2 = load i64* %a + store i64 %v2, i64* bitcast ([2 x float]* @complex2 to i64*) + ret void +} + +define float @test27() { +; Another, more complex case of splittable i64 loads and stores. This example +; is a particularly challenging one because the load and store both point into +; the alloca SROA is processing, and they overlap but at an offset. +; +; CHECK-LABEL: @test27( +; CHECK-NOT: alloca +; CHECK: %[[F1:.*]] = bitcast i32 0 to float +; CHECK: %[[F2:.*]] = bitcast i32 1065353216 to float +; CHECK: %[[SUM:.*]] = fadd float %[[F1]], %[[F2]] +; CHECK: ret float %[[SUM]] + +entry: + %a = alloca [12 x i8] + %gep1 = getelementptr [12 x i8]* %a, i32 0, i32 0 + %gep2 = getelementptr [12 x i8]* %a, i32 0, i32 4 + %gep3 = getelementptr [12 x i8]* %a, i32 0, i32 8 + %iptr1 = bitcast i8* %gep1 to i64* + %iptr2 = bitcast i8* %gep2 to i64* + %fptr1 = bitcast i8* %gep1 to float* + %fptr2 = bitcast i8* %gep2 to float* + %fptr3 = bitcast i8* %gep3 to float* + store float 0.0, float* %fptr1 + store float 1.0, float* %fptr2 + %v = load i64* %iptr1 + store i64 %v, i64* %iptr2 + %f1 = load float* %fptr2 + %f2 = load float* %fptr3 + %ret = fadd float %f1, %f2 + ret float %ret +} + +define i32 @PR22093() { +; Test that we don't try to pre-split a splittable store of a splittable but +; not pre-splittable load over the same alloca. We "handle" this case when the +; load is unsplittable but unrelated to this alloca by just generating extra +; loads without touching the original, but when the original load was out of +; this alloca we need to handle it specially to ensure the splits line up +; properly for rewriting. +; +; CHECK-LABEL: @PR22093( +; CHECK-NOT: alloca +; CHECK: alloca i16 +; CHECK-NOT: alloca +; CHECK: store volatile i16 + +entry: + %a = alloca i32 + %a.cast = bitcast i32* %a to i16* + store volatile i16 42, i16* %a.cast + %load = load i32* %a + store i32 %load, i32* %a + ret i32 %load +} + +define void @PR22093.2() { +; Another way that we end up being unable to split a particular set of loads +; and stores can even have ordering importance. Here we have a load which is +; pre-splittable by itself, and the first store is also compatible. But the +; second store of the load makes the load unsplittable because of a mismatch of +; splits. Because this makes the load unsplittable, we also have to go back and +; remove the first store from the presplit candidates as its load won't be +; presplit. +; +; CHECK-LABEL: @PR22093.2( +; CHECK-NOT: alloca +; CHECK: alloca i16 +; CHECK-NEXT: alloca i8 +; CHECK-NOT: alloca +; CHECK: store volatile i16 +; CHECK: store volatile i8 + +entry: + %a = alloca i64 + %a.cast1 = bitcast i64* %a to i32* + %a.cast2 = bitcast i64* %a to i16* + store volatile i16 42, i16* %a.cast2 + %load = load i32* %a.cast1 + store i32 %load, i32* %a.cast1 + %a.gep1 = getelementptr i32* %a.cast1, i32 1 + %a.cast3 = bitcast i32* %a.gep1 to i8* + store volatile i8 13, i8* %a.cast3 + store i32 %load, i32* %a.gep1 + ret void +} diff --git a/test/Transforms/SROA/phi-and-select.ll b/test/Transforms/SROA/phi-and-select.ll index 946bc40b0587..f2870127352c 100644 --- a/test/Transforms/SROA/phi-and-select.ll +++ b/test/Transforms/SROA/phi-and-select.ll @@ -502,6 +502,71 @@ end: ; CHECK: ret float %[[phi]] } +; Verifies we fixed PR20425. We should be able to promote all alloca's to +; registers in this test. +; +; %0 = slice +; %1 = slice +; %2 = phi(%0, %1) // == slice +define float @simplify_phi_nodes_that_equal_slice(i1 %cond, float* %temp) { +; CHECK-LABEL: @simplify_phi_nodes_that_equal_slice( +entry: + %arr = alloca [4 x float], align 4 +; CHECK-NOT: alloca + br i1 %cond, label %then, label %else + +then: + %0 = getelementptr inbounds [4 x float]* %arr, i64 0, i64 3 + store float 1.000000e+00, float* %0, align 4 + br label %merge + +else: + %1 = getelementptr inbounds [4 x float]* %arr, i64 0, i64 3 + store float 2.000000e+00, float* %1, align 4 + br label %merge + +merge: + %2 = phi float* [ %0, %then ], [ %1, %else ] + store float 0.000000e+00, float* %temp, align 4 + %3 = load float* %2, align 4 + ret float %3 +} + +; A slightly complicated example for PR20425. +; +; %0 = slice +; %1 = phi(%0) // == slice +; %2 = slice +; %3 = phi(%1, %2) // == slice +define float @simplify_phi_nodes_that_equal_slice_2(i1 %cond, float* %temp) { +; CHECK-LABEL: @simplify_phi_nodes_that_equal_slice_2( +entry: + %arr = alloca [4 x float], align 4 +; CHECK-NOT: alloca + br i1 %cond, label %then, label %else + +then: + %0 = getelementptr inbounds [4 x float]* %arr, i64 0, i64 3 + store float 1.000000e+00, float* %0, align 4 + br label %then2 + +then2: + %1 = phi float* [ %0, %then ] + store float 2.000000e+00, float* %1, align 4 + br label %merge + +else: + %2 = getelementptr inbounds [4 x float]* %arr, i64 0, i64 3 + store float 3.000000e+00, float* %2, align 4 + br label %merge + +merge: + %3 = phi float* [ %1, %then2 ], [ %2, %else ] + store float 0.000000e+00, float* %temp, align 4 + %4 = load float* %3, align 4 + ret float %4 +} + %struct.S = type { i32 } ; Verifies we fixed PR20822. We have a foldable PHI feeding a speculatable PHI @@ -514,7 +579,6 @@ define void @PR20822() { entry: %f = alloca %struct.S, align 4 ; CHECK: %[[alloca:.*]] = alloca -; CHECK: %[[cast:.*]] = bitcast i32* %[[alloca]] to %struct.S* br i1 undef, label %if.end, label %for.cond for.cond: ; preds = %for.cond, %entry @@ -522,8 +586,8 @@ for.cond: ; preds = %for.cond, %entry if.end: ; preds = %for.cond, %entry %f2 = phi %struct.S* [ %f, %entry ], [ %f, %for.cond ] -; CHECK: phi {{.*}} %[[cast]] ; CHECK: phi i32 +; CHECK: %[[cast:.*]] = bitcast i32* %[[alloca]] to %struct.S* phi i32 [ undef, %entry ], [ undef, %for.cond ] br i1 undef, label %if.then5, label %if.then2 @@ -532,6 +596,7 @@ if.then2: ; preds = %if.end if.then5: ; preds = %if.then2, %if.end %f1 = phi %struct.S* [ undef, %if.then2 ], [ %f2, %if.end ] +; CHECK: phi {{.*}} %[[cast]] store %struct.S undef, %struct.S* %f1, align 4 ret void } diff --git a/test/Transforms/SROA/slice-width.ll b/test/Transforms/SROA/slice-width.ll index 179780b4afee..ff66dcccee4b 100644 --- a/test/Transforms/SROA/slice-width.ll +++ b/test/Transforms/SROA/slice-width.ll @@ -1,7 +1,8 @@ ; RUN: opt < %s -sroa -S | FileCheck %s -target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32:64" +target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-f80:128-v64:64:64-v128:128:128-a0:0:64-n8:16:32:64" declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) nounwind define void @no_split_on_non_byte_width(i32) { ; This tests that allocas are not split into slices that are not byte width multiple @@ -23,3 +24,83 @@ load_i1: %t1 = load i1* %p1 ret void } + +; PR18726: Check that we use memcpy and memset to fill out padding when we have +; a slice with a simple single type whose store size is smaller than the slice +; size. + +%union.Foo = type { x86_fp80, i64, i64 } + +@foo_copy_source = external constant %union.Foo +@i64_sink = global i64 0 + +define void @memcpy_fp80_padding() { + %x = alloca %union.Foo + + ; Copy from a global. + %x_i8 = bitcast %union.Foo* %x to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x_i8, i8* bitcast (%union.Foo* @foo_copy_source to i8*), i32 32, i32 16, i1 false) + + ; Access a slice of the alloca to trigger SROA. + %mid_p = getelementptr %union.Foo* %x, i32 0, i32 1 + %elt = load i64* %mid_p + store i64 %elt, i64* @i64_sink + ret void +} +; CHECK-LABEL: define void @memcpy_fp80_padding +; CHECK: alloca x86_fp80 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32 +; CHECK: load i64* getelementptr inbounds (%union.Foo* @foo_copy_source, i64 0, i32 1) +; CHECK: load i64* getelementptr inbounds (%union.Foo* @foo_copy_source, i64 0, i32 2) + +define void @memset_fp80_padding() { + %x = alloca %union.Foo + + ; Set to all ones. + %x_i8 = bitcast %union.Foo* %x to i8* + call void @llvm.memset.p0i8.i32(i8* %x_i8, i8 -1, i32 32, i32 16, i1 false) + + ; Access a slice of the alloca to trigger SROA. + %mid_p = getelementptr %union.Foo* %x, i32 0, i32 1 + %elt = load i64* %mid_p + store i64 %elt, i64* @i64_sink + ret void +} +; CHECK-LABEL: define void @memset_fp80_padding +; CHECK: alloca x86_fp80 +; CHECK: call void @llvm.memset.p0i8.i32(i8* %{{.*}}, i8 -1, i32 16, i32 16, i1 false) +; CHECK: store i64 -1, i64* @i64_sink + +%S.vec3float = type { float, float, float } +%U.vec3float = type { <4 x float> } + +declare i32 @memcpy_vec3float_helper(%S.vec3float*) + +define i32 @memcpy_vec3float_widening(%S.vec3float* %x) { +; CHECK-LABEL: @memcpy_vec3float_widening( +; PR18726: Check that SROA does not rewrite a 12-byte memcpy into a 16-byte +; vector store, hence accidentally putting gibberish onto the stack. +entry: + ; Create a temporary variable %tmp1 and copy %x[0] into it + %tmp1 = alloca %S.vec3float, align 4 + %0 = bitcast %S.vec3float* %tmp1 to i8* + %1 = bitcast %S.vec3float* %x to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* %1, i32 12, i32 4, i1 false) + + ; The following block does nothing; but appears to confuse SROA + %unused1 = bitcast %S.vec3float* %tmp1 to %U.vec3float* + %unused2 = getelementptr inbounds %U.vec3float* %unused1, i32 0, i32 0 + %unused3 = load <4 x float>* %unused2, align 1 + + ; Create a second temporary and copy %tmp1 into it + %tmp2 = alloca %S.vec3float, align 4 + %2 = bitcast %S.vec3float* %tmp2 to i8* + %3 = bitcast %S.vec3float* %tmp1 to i8* +; CHECK: alloca +; CHECK-NOT: store <4 x float> + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %2, i8* %3, i32 12, i32 4, i1 false) + + %result = call i32 @memcpy_vec3float_helper(%S.vec3float* %tmp2) + ret i32 %result +; CHECK: ret i32 %result +} diff --git a/test/Transforms/SROA/vector-lifetime-intrinsic.ll b/test/Transforms/SROA/vector-lifetime-intrinsic.ll new file mode 100644 index 000000000000..30c93b054ecc --- /dev/null +++ b/test/Transforms/SROA/vector-lifetime-intrinsic.ll @@ -0,0 +1,31 @@ +; RUN: opt -sroa -S < %s | FileCheck %s + +target datalayout = "e-p:64:32-i64:32-v32:32-n32-S64" + +; Function Attrs: nounwind +declare void @llvm.lifetime.start(i64, i8* nocapture) #0 + +; Function Attrs: nounwind +declare void @llvm.lifetime.end(i64, i8* nocapture) #0 + +; CHECK: @wombat +; CHECK-NOT: alloca +; CHECK: ret void +define void @wombat(<4 x float> %arg1) { +bb: + %tmp = alloca <4 x float>, align 16 + %tmp8 = bitcast <4 x float>* %tmp to i8* + call void @llvm.lifetime.start(i64 16, i8* %tmp8) + store <4 x float> %arg1, <4 x float>* %tmp, align 16 + %tmp17 = bitcast <4 x float>* %tmp to <3 x float>* + %tmp18 = load <3 x float>* %tmp17 + %tmp20 = bitcast <4 x float>* %tmp to i8* + call void @llvm.lifetime.end(i64 16, i8* %tmp20) + call void @wombat3(<3 x float> %tmp18) + ret void +} + +; Function Attrs: nounwind +declare void @wombat3(<3 x float>) #0 + +attributes #0 = { nounwind } diff --git a/test/Transforms/SROA/vector-promotion.ll b/test/Transforms/SROA/vector-promotion.ll index 9c9f6a1d08d4..c20c6352e099 100644 --- a/test/Transforms/SROA/vector-promotion.ll +++ b/test/Transforms/SROA/vector-promotion.ll @@ -468,3 +468,158 @@ entry: ; CHECK: %[[insert:.*]] = or i32 %{{.*}}, %[[trunc]] ; CHECK: ret i32 %[[insert]] } + +define i32 @test7(<2 x i32> %x, <2 x i32> %y) { +; Test that we can promote to vectors when the alloca doesn't mention any vector types. +; CHECK-LABEL: @test7( +entry: + %a = alloca [2 x i64] + %a.cast = bitcast [2 x i64]* %a to [2 x <2 x i32>]* +; CHECK-NOT: alloca + + %a.x = getelementptr inbounds [2 x <2 x i32>]* %a.cast, i64 0, i64 0 + store <2 x i32> %x, <2 x i32>* %a.x + %a.y = getelementptr inbounds [2 x <2 x i32>]* %a.cast, i64 0, i64 1 + store <2 x i32> %y, <2 x i32>* %a.y +; CHECK-NOT: store + + %a.tmp1 = getelementptr inbounds [2 x <2 x i32>]* %a.cast, i64 0, i64 0, i64 1 + %tmp1 = load i32* %a.tmp1 + %a.tmp2 = getelementptr inbounds [2 x <2 x i32>]* %a.cast, i64 0, i64 1, i64 1 + %tmp2 = load i32* %a.tmp2 + %a.tmp3 = getelementptr inbounds [2 x <2 x i32>]* %a.cast, i64 0, i64 1, i64 0 + %tmp3 = load i32* %a.tmp3 +; CHECK-NOT: load +; CHECK: extractelement <2 x i32> %x, i32 1 +; CHECK-NEXT: extractelement <2 x i32> %y, i32 1 +; CHECK-NEXT: extractelement <2 x i32> %y, i32 0 + + %tmp4 = add i32 %tmp1, %tmp2 + %tmp5 = add i32 %tmp3, %tmp4 + ret i32 %tmp5 +; CHECK-NEXT: add +; CHECK-NEXT: add +; CHECK-NEXT: ret +} + +define i32 @test8(<2 x i32> %x) { +; Ensure that we can promote an alloca that doesn't mention a vector type based +; on a single store with a vector type. +; CHECK-LABEL: @test8( +entry: + %a = alloca i64 + %a.vec = bitcast i64* %a to <2 x i32>* + %a.i32 = bitcast i64* %a to i32* +; CHECK-NOT: alloca + + store <2 x i32> %x, <2 x i32>* %a.vec +; CHECK-NOT: store + + %tmp1 = load i32* %a.i32 + %a.tmp2 = getelementptr inbounds i32* %a.i32, i64 1 + %tmp2 = load i32* %a.tmp2 +; CHECK-NOT: load +; CHECK: extractelement <2 x i32> %x, i32 0 +; CHECK-NEXT: extractelement <2 x i32> %x, i32 1 + + %tmp4 = add i32 %tmp1, %tmp2 + ret i32 %tmp4 +; CHECK-NEXT: add +; CHECK-NEXT: ret +} + +define <2 x i32> @test9(i32 %x, i32 %y) { +; Ensure that we can promote an alloca that doesn't mention a vector type based +; on a single load with a vector type. +; CHECK-LABEL: @test9( +entry: + %a = alloca i64 + %a.vec = bitcast i64* %a to <2 x i32>* + %a.i32 = bitcast i64* %a to i32* +; CHECK-NOT: alloca + + store i32 %x, i32* %a.i32 + %a.tmp2 = getelementptr inbounds i32* %a.i32, i64 1 + store i32 %y, i32* %a.tmp2 +; CHECK-NOT: store +; CHECK: %[[V1:.*]] = insertelement <2 x i32> undef, i32 %x, i32 0 +; CHECK-NEXT: %[[V2:.*]] = insertelement <2 x i32> %[[V1]], i32 %y, i32 1 + + %result = load <2 x i32>* %a.vec +; CHECK-NOT: load + + ret <2 x i32> %result +; CHECK-NEXT: ret <2 x i32> %[[V2]] +} + +define <2 x i32> @test10(<4 x i16> %x, i32 %y) { +; If there are multiple different vector types used, we should select the one +; with the widest elements. +; CHECK-LABEL: @test10( +entry: + %a = alloca i64 + %a.vec1 = bitcast i64* %a to <2 x i32>* + %a.vec2 = bitcast i64* %a to <4 x i16>* + %a.i32 = bitcast i64* %a to i32* +; CHECK-NOT: alloca + + store <4 x i16> %x, <4 x i16>* %a.vec2 + %a.tmp2 = getelementptr inbounds i32* %a.i32, i64 1 + store i32 %y, i32* %a.tmp2 +; CHECK-NOT: store +; CHECK: %[[V1:.*]] = bitcast <4 x i16> %x to <2 x i32> +; CHECK-NEXT: %[[V2:.*]] = insertelement <2 x i32> %[[V1]], i32 %y, i32 1 + + %result = load <2 x i32>* %a.vec1 +; CHECK-NOT: load + + ret <2 x i32> %result +; CHECK-NEXT: ret <2 x i32> %[[V2]] +} + +define <2 x float> @test11(<4 x i16> %x, i32 %y) { +; If there are multiple different element types for different vector types, +; pick the integer types. This isn't really important, but seems like the best +; heuristic for making a deterministic decision. +; CHECK-LABEL: @test11( +entry: + %a = alloca i64 + %a.vec1 = bitcast i64* %a to <2 x float>* + %a.vec2 = bitcast i64* %a to <4 x i16>* + %a.i32 = bitcast i64* %a to i32* +; CHECK-NOT: alloca + + store <4 x i16> %x, <4 x i16>* %a.vec2 + %a.tmp2 = getelementptr inbounds i32* %a.i32, i64 1 + store i32 %y, i32* %a.tmp2 +; CHECK-NOT: store +; CHECK: %[[V1:.*]] = bitcast i32 %y to <2 x i16> +; CHECK-NEXT: %[[V2:.*]] = shufflevector <2 x i16> %[[V1]], <2 x i16> undef, <4 x i32> <i32 undef, i32 undef, i32 0, i32 1> +; CHECK-NEXT: %[[V3:.*]] = select <4 x i1> <i1 false, i1 false, i1 true, i1 true>, <4 x i16> %[[V2]], <4 x i16> %x +; CHECK-NEXT: %[[V4:.*]] = bitcast <4 x i16> %[[V3]] to <2 x float> + + %result = load <2 x float>* %a.vec1 +; CHECK-NOT: load + + ret <2 x float> %result +; CHECK-NEXT: ret <2 x float> %[[V4]] +} + +define <4 x float> @test12() { +; CHECK-LABEL: @test12( + %a = alloca <3 x i32>, align 16 +; CHECK-NOT: alloca + + %cast1 = bitcast <3 x i32>* %a to <4 x i32>* + store <4 x i32> undef, <4 x i32>* %cast1, align 16 +; CHECK-NOT: store + + %cast2 = bitcast <3 x i32>* %a to <3 x float>* + %cast3 = bitcast <3 x float>* %cast2 to <4 x float>* + %vec = load <4 x float>* %cast3 +; CHECK-NOT: load + +; CHECK: %[[ret:.*]] = bitcast <4 x i32> undef to <4 x float> +; CHECK-NEXT: ret <4 x float> %[[ret]] + ret <4 x float> %vec +} diff --git a/test/Transforms/SampleProfile/Inputs/fnptr.binprof b/test/Transforms/SampleProfile/Inputs/fnptr.binprof Binary files differnew file mode 100644 index 000000000000..14d7fd555dae --- /dev/null +++ b/test/Transforms/SampleProfile/Inputs/fnptr.binprof diff --git a/test/Transforms/SampleProfile/Inputs/fnptr.prof b/test/Transforms/SampleProfile/Inputs/fnptr.prof new file mode 100644 index 000000000000..6a3b4e2315bb --- /dev/null +++ b/test/Transforms/SampleProfile/Inputs/fnptr.prof @@ -0,0 +1,12 @@ +_Z3fooi:7711:610 +1: 610 +_Z3bari:20301:1437 +1: 1437 +main:184019:0 +4: 534 +6: 2080 +9: 2064 _Z3bari:1471 _Z3fooi:631 +5.1: 1075 +5: 1075 +7: 534 +4.2: 534 diff --git a/test/Transforms/SampleProfile/branch.ll b/test/Transforms/SampleProfile/branch.ll index 65f1f1769934..6391fc5158cf 100644 --- a/test/Transforms/SampleProfile/branch.ll +++ b/test/Transforms/SampleProfile/branch.ll @@ -32,8 +32,8 @@ define i32 @main(i32 %argc, i8** nocapture readonly %argv) #0 { ; CHECK: Printing analysis 'Branch Probability Analysis' for function 'main': entry: - tail call void @llvm.dbg.value(metadata !{i32 %argc}, i64 0, metadata !13), !dbg !27 - tail call void @llvm.dbg.value(metadata !{i8** %argv}, i64 0, metadata !14), !dbg !27 + tail call void @llvm.dbg.value(metadata i32 %argc, i64 0, metadata !13, metadata !{}), !dbg !27 + tail call void @llvm.dbg.value(metadata i8** %argv, i64 0, metadata !14, metadata !{}), !dbg !27 %cmp = icmp slt i32 %argc, 2, !dbg !28 br i1 %cmp, label %return, label %if.end, !dbg !28 ; CHECK: edge entry -> return probability is 1 / 2 = 50% @@ -43,7 +43,7 @@ if.end: ; preds = %entry %arrayidx = getelementptr inbounds i8** %argv, i64 1, !dbg !30 %0 = load i8** %arrayidx, align 8, !dbg !30, !tbaa !31 %call = tail call i32 @atoi(i8* %0) #4, !dbg !30 - tail call void @llvm.dbg.value(metadata !{i32 %call}, i64 0, metadata !17), !dbg !30 + tail call void @llvm.dbg.value(metadata i32 %call, i64 0, metadata !17, metadata !{}), !dbg !30 %cmp1 = icmp sgt i32 %call, 100, !dbg !35 br i1 %cmp1, label %for.body, label %if.end6, !dbg !35 ; CHECK: edge if.end -> for.body probability is 1 / 2 = 50% @@ -55,14 +55,14 @@ for.body: ; preds = %if.end, %for.body %add = fadd double %s.015, 3.049000e+00, !dbg !36 %conv = sitofp i32 %u.016 to double, !dbg !36 %add4 = fadd double %add, %conv, !dbg !36 - tail call void @llvm.dbg.value(metadata !{double %add4}, i64 0, metadata !18), !dbg !36 + tail call void @llvm.dbg.value(metadata double %add4, i64 0, metadata !18, metadata !{}), !dbg !36 %div = fdiv double 3.940000e+00, %s.015, !dbg !37 %mul = fmul double %div, 3.200000e-01, !dbg !37 %add5 = fadd double %add4, %mul, !dbg !37 %sub = fsub double %add4, %add5, !dbg !37 - tail call void @llvm.dbg.value(metadata !{double %sub}, i64 0, metadata !18), !dbg !37 + tail call void @llvm.dbg.value(metadata double %sub, i64 0, metadata !18, metadata !{}), !dbg !37 %inc = add nsw i32 %u.016, 1, !dbg !38 - tail call void @llvm.dbg.value(metadata !{i32 %inc}, i64 0, metadata !21), !dbg !38 + tail call void @llvm.dbg.value(metadata i32 %inc, i64 0, metadata !21, metadata !{}), !dbg !38 %exitcond = icmp eq i32 %inc, %call, !dbg !38 br i1 %exitcond, label %if.end6, label %for.body, !dbg !38 ; CHECK: edge for.body -> if.end6 probability is 1 / 10227 = 0.00977804 @@ -86,7 +86,7 @@ declare i32 @atoi(i8* nocapture) #1 declare i32 @printf(i8* nocapture readonly, ...) #2 ; Function Attrs: nounwind readnone -declare void @llvm.dbg.value(metadata, i64, metadata) #3 +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #3 attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readonly "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } @@ -98,46 +98,46 @@ attributes #4 = { nounwind readonly } !llvm.module.flags = !{!25, !42} !llvm.ident = !{!26} -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.4 (trunk 192896) (llvm/trunk 192895)", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [./branch.cc] [DW_LANG_C_plus_plus] -!1 = metadata !{metadata !"branch.cc", metadata !"."} -!2 = metadata !{i32 0} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"main", metadata !"main", metadata !"", i32 4, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i32 (i32, i8**)* @main, null, null, metadata !12, i32 4} ; [ DW_TAG_subprogram ] [line 4] [def] [main] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [./branch.cc] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{metadata !8, metadata !8, metadata !9} -!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] -!9 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !10} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ] -!10 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !11} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from char] -!11 = metadata !{i32 786468, null, null, metadata !"char", i32 0, i64 8, i64 8, i64 0, i32 0, i32 6} ; [ DW_TAG_base_type ] [char] [line 0, size 8, align 8, offset 0, enc DW_ATE_signed_char] -!12 = metadata !{metadata !13, metadata !14, metadata !15, metadata !17, metadata !18, metadata !21, metadata !23} -!13 = metadata !{i32 786689, metadata !4, metadata !"argc", metadata !5, i32 16777220, metadata !8, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [argc] [line 4] -!14 = metadata !{i32 786689, metadata !4, metadata !"argv", metadata !5, i32 33554436, metadata !9, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [argv] [line 4] -!15 = metadata !{i32 786688, metadata !4, metadata !"result", metadata !5, i32 7, metadata !16, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [result] [line 7] -!16 = metadata !{i32 786468, null, null, metadata !"double", i32 0, i64 64, i64 64, i64 0, i32 0, i32 4} ; [ DW_TAG_base_type ] [double] [line 0, size 64, align 64, offset 0, enc DW_ATE_float] -!17 = metadata !{i32 786688, metadata !4, metadata !"limit", metadata !5, i32 8, metadata !8, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [limit] [line 8] -!18 = metadata !{i32 786688, metadata !19, metadata !"s", metadata !5, i32 10, metadata !16, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [s] [line 10] -!19 = metadata !{i32 786443, metadata !1, metadata !20, i32 9, i32 0, i32 0, i32 2} ; [ DW_TAG_lexical_block ] [./branch.cc] -!20 = metadata !{i32 786443, metadata !1, metadata !4, i32 9, i32 0, i32 0, i32 1} ; [ DW_TAG_lexical_block ] [./branch.cc] -!21 = metadata !{i32 786688, metadata !22, metadata !"u", metadata !5, i32 11, metadata !8, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [u] [line 11] -!22 = metadata !{i32 786443, metadata !1, metadata !19, i32 11, i32 0, i32 0, i32 3} ; [ DW_TAG_lexical_block ] [./branch.cc] -!23 = metadata !{i32 786688, metadata !24, metadata !"x", metadata !5, i32 12, metadata !16, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [x] [line 12] -!24 = metadata !{i32 786443, metadata !1, metadata !22, i32 11, i32 0, i32 0, i32 4} ; [ DW_TAG_lexical_block ] [./branch.cc] -!25 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!26 = metadata !{metadata !"clang version 3.4 (trunk 192896) (llvm/trunk 192895)"} -!27 = metadata !{i32 4, i32 0, metadata !4, null} -!28 = metadata !{i32 5, i32 0, metadata !29, null} -!29 = metadata !{i32 786443, metadata !1, metadata !4, i32 5, i32 0, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [./branch.cc] -!30 = metadata !{i32 8, i32 0, metadata !4, null} ; [ DW_TAG_imported_declaration ] -!31 = metadata !{metadata !32, metadata !32, i64 0} -!32 = metadata !{metadata !"any pointer", metadata !33, i64 0} -!33 = metadata !{metadata !"omnipotent char", metadata !34, i64 0} -!34 = metadata !{metadata !"Simple C/C++ TBAA"} -!35 = metadata !{i32 9, i32 0, metadata !20, null} -!36 = metadata !{i32 13, i32 0, metadata !24, null} -!37 = metadata !{i32 14, i32 0, metadata !24, null} -!38 = metadata !{i32 11, i32 0, metadata !22, null} -!39 = metadata !{i32 20, i32 0, metadata !4, null} -!40 = metadata !{i32 21, i32 0, metadata !4, null} -!41 = metadata !{i32 22, i32 0, metadata !4, null} -!42 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x11\004\00clang version 3.4 (trunk 192896) (llvm/trunk 192895)\001\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [./branch.cc] [DW_LANG_C_plus_plus] +!1 = !{!"branch.cc", !"."} +!2 = !{i32 0} +!3 = !{!4} +!4 = !{!"0x2e\00main\00main\00\004\000\001\000\006\00256\001\004", !1, !5, !6, null, i32 (i32, i8**)* @main, null, null, !12} ; [ DW_TAG_subprogram ] [line 4] [def] [main] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [./branch.cc] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{!8, !8, !9} +!8 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!9 = !{!"0xf\00\000\0064\0064\000\000", null, null, !10} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ] +!10 = !{!"0xf\00\000\0064\0064\000\000", null, null, !11} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from char] +!11 = !{!"0x24\00char\000\008\008\000\000\006", null, null} ; [ DW_TAG_base_type ] [char] [line 0, size 8, align 8, offset 0, enc DW_ATE_signed_char] +!12 = !{!13, !14, !15, !17, !18, !21, !23} +!13 = !{!"0x101\00argc\0016777220\000", !4, !5, !8} ; [ DW_TAG_arg_variable ] [argc] [line 4] +!14 = !{!"0x101\00argv\0033554436\000", !4, !5, !9} ; [ DW_TAG_arg_variable ] [argv] [line 4] +!15 = !{!"0x100\00result\007\000", !4, !5, !16} ; [ DW_TAG_auto_variable ] [result] [line 7] +!16 = !{!"0x24\00double\000\0064\0064\000\000\004", null, null} ; [ DW_TAG_base_type ] [double] [line 0, size 64, align 64, offset 0, enc DW_ATE_float] +!17 = !{!"0x100\00limit\008\000", !4, !5, !8} ; [ DW_TAG_auto_variable ] [limit] [line 8] +!18 = !{!"0x100\00s\0010\000", !19, !5, !16} ; [ DW_TAG_auto_variable ] [s] [line 10] +!19 = !{!"0xb\009\000\000", !1, !20} ; [ DW_TAG_lexical_block ] [./branch.cc] +!20 = !{!"0xb\009\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [./branch.cc] +!21 = !{!"0x100\00u\0011\000", !22, !5, !8} ; [ DW_TAG_auto_variable ] [u] [line 11] +!22 = !{!"0xb\0011\000\000", !1, !19} ; [ DW_TAG_lexical_block ] [./branch.cc] +!23 = !{!"0x100\00x\0012\000", !24, !5, !16} ; [ DW_TAG_auto_variable ] [x] [line 12] +!24 = !{!"0xb\0011\000\000", !1, !22} ; [ DW_TAG_lexical_block ] [./branch.cc] +!25 = !{i32 2, !"Dwarf Version", i32 4} +!26 = !{!"clang version 3.4 (trunk 192896) (llvm/trunk 192895)"} +!27 = !MDLocation(line: 4, scope: !4) +!28 = !MDLocation(line: 5, scope: !29) +!29 = !{!"0xb\005\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [./branch.cc] +!30 = !MDLocation(line: 8, scope: !4) +!31 = !{!32, !32, i64 0} +!32 = !{!"any pointer", !33, i64 0} +!33 = !{!"omnipotent char", !34, i64 0} +!34 = !{!"Simple C/C++ TBAA"} +!35 = !MDLocation(line: 9, scope: !20) +!36 = !MDLocation(line: 13, scope: !24) +!37 = !MDLocation(line: 14, scope: !24) +!38 = !MDLocation(line: 11, scope: !22) +!39 = !MDLocation(line: 20, scope: !4) +!40 = !MDLocation(line: 21, scope: !4) +!41 = !MDLocation(line: 22, scope: !4) +!42 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/SampleProfile/calls.ll b/test/Transforms/SampleProfile/calls.ll index 381be8714eb6..d56660937bc0 100644 --- a/test/Transforms/SampleProfile/calls.ll +++ b/test/Transforms/SampleProfile/calls.ll @@ -15,7 +15,12 @@ ; printf("sum is %d\n", s); ; return 0; ; } - +; +; Note that this test is missing the llvm.dbg.cu annotation. This emulates +; the effect of the user having only used -fprofile-sample-use without +; -gmlt when invoking the driver. In those cases, we need to track source +; location information but we do not have to generate debug info in the +; final binary. @.str = private unnamed_addr constant [11 x i8] c"sum is %d\0A\00", align 1 ; Function Attrs: nounwind uwtable @@ -84,33 +89,32 @@ while.end: ; preds = %while.cond declare i32 @printf(i8*, ...) #2 -!llvm.dbg.cu = !{!0} !llvm.module.flags = !{!8, !9} !llvm.ident = !{!10} -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.5 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [./calls.cc] [DW_LANG_C_plus_plus] -!1 = metadata !{metadata !"calls.cc", metadata !"."} -!2 = metadata !{} -!3 = metadata !{metadata !4, metadata !7} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"sum", metadata !"sum", metadata !"", i32 3, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32, i32)* @_Z3sumii, null, null, metadata !2, i32 3} ; [ DW_TAG_subprogram ] [line 3] [def] [sum] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [./calls.cc] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"main", metadata !"main", metadata !"", i32 7, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 ()* @main, null, null, metadata !2, i32 7} ; [ DW_TAG_subprogram ] [line 7] [def] [main] -!8 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!9 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} -!10 = metadata !{metadata !"clang version 3.5 "} -!11 = metadata !{i32 4, i32 0, metadata !4, null} -!12 = metadata !{i32 8, i32 0, metadata !7, null} ; [ DW_TAG_imported_declaration ] -!13 = metadata !{i32 9, i32 0, metadata !7, null} -!14 = metadata !{i32 9, i32 0, metadata !15, null} -!15 = metadata !{i32 786443, metadata !1, metadata !7, i32 9, i32 0, i32 1, i32 1} ; [ DW_TAG_lexical_block ] [./calls.cc] -!16 = metadata !{i32 10, i32 0, metadata !17, null} -!17 = metadata !{i32 786443, metadata !1, metadata !7, i32 10, i32 0, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [./calls.cc] -!18 = metadata !{i32 10, i32 0, metadata !19, null} -!19 = metadata !{i32 786443, metadata !1, metadata !17, i32 10, i32 0, i32 1, i32 2} ; [ DW_TAG_lexical_block ] [./calls.cc] -!20 = metadata !{i32 10, i32 0, metadata !21, null} -!21 = metadata !{i32 786443, metadata !1, metadata !17, i32 10, i32 0, i32 2, i32 3} ; [ DW_TAG_lexical_block ] [./calls.cc] -!22 = metadata !{i32 10, i32 0, metadata !23, null} -!23 = metadata !{i32 786443, metadata !1, metadata !17, i32 10, i32 0, i32 3, i32 4} ; [ DW_TAG_lexical_block ] [./calls.cc] -!24 = metadata !{i32 11, i32 0, metadata !7, null} -!25 = metadata !{i32 12, i32 0, metadata !7, null} +!0 = !{!"0x11\004\00clang version 3.5 \000\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [./calls.cc] [DW_LANG_C_plus_plus] +!1 = !{!"calls.cc", !"."} +!2 = !{} +!3 = !{!4, !7} +!4 = !{!"0x2e\00sum\00sum\00\003\000\001\000\006\00256\000\003", !1, !5, !6, null, i32 (i32, i32)* @_Z3sumii, null, null, !2} ; [ DW_TAG_subprogram ] [line 3] [def] [sum] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [./calls.cc] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{!"0x2e\00main\00main\00\007\000\001\000\006\00256\000\007", !1, !5, !6, null, i32 ()* @main, null, null, !2} ; [ DW_TAG_subprogram ] [line 7] [def] [main] +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 1, !"Debug Info Version", i32 2} +!10 = !{!"clang version 3.5 "} +!11 = !MDLocation(line: 4, scope: !4) +!12 = !MDLocation(line: 8, scope: !7) +!13 = !MDLocation(line: 9, scope: !7) +!14 = !MDLocation(line: 9, scope: !15) +!15 = !{!"0xb\001", !1, !7} ; [ DW_TAG_lexical_block ] [./calls.cc] +!16 = !MDLocation(line: 10, scope: !17) +!17 = !{!"0xb\0010\000\000", !1, !7} ; [ DW_TAG_lexical_block ] [./calls.cc] +!18 = !MDLocation(line: 10, scope: !19) +!19 = !{!"0xb\001", !1, !17} ; [ DW_TAG_lexical_block ] [./calls.cc] +!20 = !MDLocation(line: 10, scope: !21) +!21 = !{!"0xb\002", !1, !17} ; [ DW_TAG_lexical_block ] [./calls.cc] +!22 = !MDLocation(line: 10, scope: !23) +!23 = !{!"0xb\003", !1, !17} ; [ DW_TAG_lexical_block ] [./calls.cc] +!24 = !MDLocation(line: 11, scope: !7) +!25 = !MDLocation(line: 12, scope: !7) diff --git a/test/Transforms/SampleProfile/discriminator.ll b/test/Transforms/SampleProfile/discriminator.ll index 0f773a541a4e..cafc69d14923 100644 --- a/test/Transforms/SampleProfile/discriminator.ll +++ b/test/Transforms/SampleProfile/discriminator.ll @@ -66,25 +66,25 @@ while.end: ; preds = %while.cond !llvm.module.flags = !{!7, !8} !llvm.ident = !{!9} -!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [discriminator.c] [DW_LANG_C99] -!1 = metadata !{metadata !"discriminator.c", metadata !"."} -!2 = metadata !{} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32)* @foo, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [discriminator.c] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!8 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} -!9 = metadata !{metadata !"clang version 3.5 "} -!10 = metadata !{i32 2, i32 0, metadata !4, null} -!11 = metadata !{i32 3, i32 0, metadata !4, null} -!12 = metadata !{i32 3, i32 0, metadata !13, null} -!13 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 0, i32 1, i32 2} ; [ DW_TAG_lexical_block ] [discriminator.c] -!14 = metadata !{i32 4, i32 0, metadata !15, null} -!15 = metadata !{i32 786443, metadata !1, metadata !16, i32 4, i32 0, i32 0, i32 1} ; [ DW_TAG_lexical_block ] [discriminator.c] -!16 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 0, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [discriminator.c] -!17 = metadata !{i32 4, i32 0, metadata !18, null} -!18 = metadata !{i32 786443, metadata !1, metadata !15, i32 4, i32 0, i32 1, i32 3} ; [ DW_TAG_lexical_block ] [discriminator.c] -!19 = metadata !{i32 5, i32 0, metadata !16, null} -!20 = metadata !{i32 6, i32 0, metadata !16, null} -!21 = metadata !{i32 7, i32 0, metadata !4, null} +!0 = !{!"0x11\0012\00clang version 3.5 \000\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [discriminator.c] [DW_LANG_C99] +!1 = !{!"discriminator.c", !"."} +!2 = !{} +!3 = !{!4} +!4 = !{!"0x2e\00foo\00foo\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, i32 (i32)* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [discriminator.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 1, !"Debug Info Version", i32 2} +!9 = !{!"clang version 3.5 "} +!10 = !MDLocation(line: 2, scope: !4) +!11 = !MDLocation(line: 3, scope: !4) +!12 = !MDLocation(line: 3, scope: !13) +!13 = !{!"0xb\001", !1, !4} ; [ DW_TAG_lexical_block ] [discriminator.c] +!14 = !MDLocation(line: 4, scope: !15) +!15 = !{!"0xb\004\000\001", !1, !16} ; [ DW_TAG_lexical_block ] [discriminator.c] +!16 = !{!"0xb\003\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [discriminator.c] +!17 = !MDLocation(line: 4, scope: !18) +!18 = !{!"0xb\001", !1, !15} ; [ DW_TAG_lexical_block ] [discriminator.c] +!19 = !MDLocation(line: 5, scope: !16) +!20 = !MDLocation(line: 6, scope: !16) +!21 = !MDLocation(line: 7, scope: !4) diff --git a/test/Transforms/SampleProfile/fnptr.ll b/test/Transforms/SampleProfile/fnptr.ll new file mode 100644 index 000000000000..096033bd35fc --- /dev/null +++ b/test/Transforms/SampleProfile/fnptr.ll @@ -0,0 +1,155 @@ +; The two profiles used in this test are the same but encoded in different +; formats. This checks that we produce the same profile annotations regardless +; of the profile format. +; +; RUN: opt < %s -sample-profile -sample-profile-file=%S/Inputs/fnptr.prof | opt -analyze -branch-prob | FileCheck %s +; RUN: opt < %s -sample-profile -sample-profile-file=%S/Inputs/fnptr.binprof | opt -analyze -branch-prob | FileCheck %s + +; CHECK: edge for.body3 -> if.then probability is 534 / 2598 = 20.5543% +; CHECK: edge for.body3 -> if.else probability is 2064 / 2598 = 79.4457% +; CHECK: edge for.inc -> for.inc12 probability is 1052 / 2598 = 40.4927% +; CHECK: edge for.inc -> for.body3 probability is 1546 / 2598 = 59.5073% +; CHECK: edge for.inc12 -> for.end14 probability is 518 / 1052 = 49.2395% +; CHECK: edge for.inc12 -> for.cond1.preheader probability is 534 / 1052 = 50.7605% + +; Original C++ test case. +; +; #include <stdlib.h> +; #include <math.h> +; #include <stdio.h> +; +; #define N 10000 +; #define M 6000 +; +; double foo(int x) { +; return x * sin((double)x); +; } +; +; double bar(int x) { +; return x - cos((double)x); +; } +; +; int main() { +; double (*fptr)(int); +; double S = 0; +; for (int i = 0; i < N; i++) +; for (int j = 0; j < M; j++) { +; fptr = (rand() % 100 < 30) ? foo : bar; +; if (rand() % 100 < 10) +; S += (*fptr)(i + j * 300); +; else +; S += (*fptr)(i - j / 840); +; } +; printf("S = %lf\n", S); +; return 0; +; } + +@.str = private unnamed_addr constant [9 x i8] c"S = %lf\0A\00", align 1 + +define double @_Z3fooi(i32 %x) #0 { +entry: + %conv = sitofp i32 %x to double, !dbg !2 + %call = tail call double @sin(double %conv) #3, !dbg !8 + %mul = fmul double %conv, %call, !dbg !8 + ret double %mul, !dbg !8 +} + +declare double @sin(double) #1 + +define double @_Z3bari(i32 %x) #0 { +entry: + %conv = sitofp i32 %x to double, !dbg !9 + %call = tail call double @cos(double %conv) #3, !dbg !11 + %sub = fsub double %conv, %call, !dbg !11 + ret double %sub, !dbg !11 +} + +declare double @cos(double) #1 + +define i32 @main() #2 { +entry: + br label %for.cond1.preheader, !dbg !12 + +for.cond1.preheader: ; preds = %for.inc12, %entry + %i.025 = phi i32 [ 0, %entry ], [ %inc13, %for.inc12 ] + %S.024 = phi double [ 0.000000e+00, %entry ], [ %S.2.lcssa, %for.inc12 ] + br label %for.body3, !dbg !14 + +for.body3: ; preds = %for.inc, %for.cond1.preheader + %j.023 = phi i32 [ 0, %for.cond1.preheader ], [ %inc, %for.inc ] + %S.122 = phi double [ %S.024, %for.cond1.preheader ], [ %S.2, %for.inc ] + %call = tail call i32 @rand() #3, !dbg !15 + %rem = srem i32 %call, 100, !dbg !15 + %cmp4 = icmp slt i32 %rem, 30, !dbg !15 + %_Z3fooi._Z3bari = select i1 %cmp4, double (i32)* @_Z3fooi, double (i32)* @_Z3bari, !dbg !15 + %call5 = tail call i32 @rand() #3, !dbg !16 + %rem6 = srem i32 %call5, 100, !dbg !16 + %cmp7 = icmp slt i32 %rem6, 10, !dbg !16 + br i1 %cmp7, label %if.then, label %if.else, !dbg !16, !prof !17 + +if.then: ; preds = %for.body3 + %mul = mul nsw i32 %j.023, 300, !dbg !18 + %add = add nsw i32 %mul, %i.025, !dbg !18 + %call8 = tail call double %_Z3fooi._Z3bari(i32 %add), !dbg !18 + br label %for.inc, !dbg !18 + +if.else: ; preds = %for.body3 + %div = sdiv i32 %j.023, 840, !dbg !19 + %sub = sub nsw i32 %i.025, %div, !dbg !19 + %call10 = tail call double %_Z3fooi._Z3bari(i32 %sub), !dbg !19 + br label %for.inc + +for.inc: ; preds = %if.then, %if.else + %call8.pn = phi double [ %call8, %if.then ], [ %call10, %if.else ] + %S.2 = fadd double %S.122, %call8.pn, !dbg !18 + %inc = add nsw i32 %j.023, 1, !dbg !20 + %exitcond = icmp eq i32 %j.023, 5999, !dbg !14 + br i1 %exitcond, label %for.inc12, label %for.body3, !dbg !14, !prof !21 + +for.inc12: ; preds = %for.inc + %S.2.lcssa = phi double [ %S.2, %for.inc ] + %inc13 = add nsw i32 %i.025, 1, !dbg !22 + %exitcond26 = icmp eq i32 %i.025, 9999, !dbg !12 + br i1 %exitcond26, label %for.end14, label %for.cond1.preheader, !dbg !12, !prof !23 + +for.end14: ; preds = %for.inc12 + %S.2.lcssa.lcssa = phi double [ %S.2.lcssa, %for.inc12 ] + %call15 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str, i64 0, i64 0), double %S.2.lcssa.lcssa), !dbg !24 + ret i32 0, !dbg !25 +} + +; Function Attrs: nounwind +declare i32 @rand() #1 + +; Function Attrs: nounwind +declare i32 @printf(i8* nocapture readonly, ...) #1 + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 2, !"Debug Info Version", i32 2} +!1 = !{!"clang version 3.6.0 "} +!2 = !MDLocation(line: 9, column: 3, scope: !3) +!3 = !{!"0x2e\00foo\00foo\00\008\000\001\000\000\00256\001\008", !4, !5, !6, null, double (i32)* @_Z3fooi, null, null, !7} ; [ DW_TAG_subprogram ] [line 8] [def] [foo] +!4 = !{!"fnptr.cc", !"."} +!5 = !{!"0x29", !4} ; [ DW_TAG_file_type ] [./fnptr.cc] +!6 = !{!"0x15\00\000\000\000\000\000\000", null, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{} +!8 = !MDLocation(line: 9, column: 14, scope: !3) +!9 = !MDLocation(line: 13, column: 3, scope: !10) +!10 = !{!"0x2e\00bar\00bar\00\0012\000\001\000\000\00256\001\0012", !4, !5, !6, null, double (i32)* @_Z3bari, null, null, !7} ; [ DW_TAG_subprogram ] [line 12] [def] [bar] +!11 = !MDLocation(line: 13, column: 14, scope: !10) +!12 = !MDLocation(line: 19, column: 3, scope: !13) +!13 = !{!"0x2e\00main\00main\00\0016\000\001\000\000\00256\001\0016", !4, !5, !6, null, i32 ()* @main, null, null, !7} ; [ DW_TAG_subprogram ] [line 16] [def] [main] +!14 = !MDLocation(line: 20, column: 5, scope: !13) +!15 = !MDLocation(line: 21, column: 15, scope: !13) +!16 = !MDLocation(line: 22, column: 11, scope: !13) +!17 = !{!"branch_weights", i32 534, i32 2064} +!18 = !MDLocation(line: 23, column: 14, scope: !13) +!19 = !MDLocation(line: 25, column: 14, scope: !13) +!20 = !MDLocation(line: 20, column: 28, scope: !13) +!21 = !{!"branch_weights", i32 0, i32 1075} +!22 = !MDLocation(line: 19, column: 26, scope: !13) +!23 = !{!"branch_weights", i32 0, i32 534} +!24 = !MDLocation(line: 27, column: 3, scope: !13) +!25 = !MDLocation(line: 28, column: 3, scope: !13) diff --git a/test/Transforms/SampleProfile/propagate.ll b/test/Transforms/SampleProfile/propagate.ll index 939361b23703..594645f7f2be 100644 --- a/test/Transforms/SampleProfile/propagate.ll +++ b/test/Transforms/SampleProfile/propagate.ll @@ -198,46 +198,46 @@ attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "n !llvm.module.flags = !{!8, !9} !llvm.ident = !{!10} -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.5 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [propagate.cc] [DW_LANG_C_plus_plus] -!1 = metadata !{metadata !"propagate.cc", metadata !"."} -!2 = metadata !{i32 0} -!3 = metadata !{metadata !4, metadata !7} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 3, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i64 (i32, i32, i64)* @_Z3fooiil, null, null, metadata !2, i32 3} ; [ DW_TAG_subprogram ] [line 3] [def] [foo] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [propagate.cc] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"main", metadata !"main", metadata !"", i32 24, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 ()* @main, null, null, metadata !2, i32 24} ; [ DW_TAG_subprogram ] [line 24] [def] [main] -!8 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!9 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} -!10 = metadata !{metadata !"clang version 3.5 "} -!11 = metadata !{i32 4, i32 0, metadata !12, null} -!12 = metadata !{i32 786443, metadata !1, metadata !4, i32 4, i32 0, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [propagate.cc] -!13 = metadata !{i32 5, i32 0, metadata !14, null} -!14 = metadata !{i32 786443, metadata !1, metadata !12, i32 4, i32 0, i32 0, i32 1} ; [ DW_TAG_lexical_block ] [propagate.cc] -!15 = metadata !{i32 7, i32 0, metadata !16, null} -!16 = metadata !{i32 786443, metadata !1, metadata !17, i32 7, i32 0, i32 0, i32 3} ; [ DW_TAG_lexical_block ] [propagate.cc] -!17 = metadata !{i32 786443, metadata !1, metadata !12, i32 6, i32 0, i32 0, i32 2} ; [ DW_TAG_lexical_block ] [propagate.cc] -!18 = metadata !{i32 8, i32 0, metadata !19, null} ; [ DW_TAG_imported_declaration ] -!19 = metadata !{i32 786443, metadata !1, metadata !20, i32 8, i32 0, i32 0, i32 5} ; [ DW_TAG_lexical_block ] [propagate.cc] -!20 = metadata !{i32 786443, metadata !1, metadata !16, i32 7, i32 0, i32 0, i32 4} ; [ DW_TAG_lexical_block ] [propagate.cc] -!21 = metadata !{i32 9, i32 0, metadata !19, null} -!22 = metadata !{i32 10, i32 0, metadata !23, null} -!23 = metadata !{i32 786443, metadata !1, metadata !20, i32 10, i32 0, i32 0, i32 6} ; [ DW_TAG_lexical_block ] [propagate.cc] -!24 = metadata !{i32 11, i32 0, metadata !25, null} -!25 = metadata !{i32 786443, metadata !1, metadata !23, i32 10, i32 0, i32 0, i32 7} ; [ DW_TAG_lexical_block ] [propagate.cc] -!26 = metadata !{i32 12, i32 0, metadata !25, null} -!27 = metadata !{i32 13, i32 0, metadata !25, null} -!28 = metadata !{i32 14, i32 0, metadata !29, null} -!29 = metadata !{i32 786443, metadata !1, metadata !30, i32 14, i32 0, i32 0, i32 9} ; [ DW_TAG_lexical_block ] [propagate.cc] -!30 = metadata !{i32 786443, metadata !1, metadata !23, i32 13, i32 0, i32 0, i32 8} ; [ DW_TAG_lexical_block ] [propagate.cc] -!31 = metadata !{i32 15, i32 0, metadata !32, null} -!32 = metadata !{i32 786443, metadata !1, metadata !29, i32 14, i32 0, i32 0, i32 10} ; [ DW_TAG_lexical_block ] [propagate.cc] -!33 = metadata !{i32 16, i32 0, metadata !32, null} -!34 = metadata !{i32 17, i32 0, metadata !32, null} -!35 = metadata !{i32 19, i32 0, metadata !20, null} -!36 = metadata !{i32 21, i32 0, metadata !4, null} -!37 = metadata !{i32 22, i32 0, metadata !4, null} -!38 = metadata !{i32 25, i32 0, metadata !7, null} -!39 = metadata !{i32 26, i32 0, metadata !7, null} -!40 = metadata !{i32 27, i32 0, metadata !7, null} -!41 = metadata !{i32 28, i32 0, metadata !7, null} -!42 = metadata !{i32 29, i32 0, metadata !7, null} +!0 = !{!"0x11\004\00clang version 3.5 \000\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [propagate.cc] [DW_LANG_C_plus_plus] +!1 = !{!"propagate.cc", !"."} +!2 = !{i32 0} +!3 = !{!4, !7} +!4 = !{!"0x2e\00foo\00foo\00\003\000\001\000\006\00256\000\003", !1, !5, !6, null, i64 (i32, i32, i64)* @_Z3fooiil, null, null, !2} ; [ DW_TAG_subprogram ] [line 3] [def] [foo] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [propagate.cc] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{!"0x2e\00main\00main\00\0024\000\001\000\006\00256\000\0024", !1, !5, !6, null, i32 ()* @main, null, null, !2} ; [ DW_TAG_subprogram ] [line 24] [def] [main] +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 1, !"Debug Info Version", i32 2} +!10 = !{!"clang version 3.5 "} +!11 = !MDLocation(line: 4, scope: !12) +!12 = !{!"0xb\004\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [propagate.cc] +!13 = !MDLocation(line: 5, scope: !14) +!14 = !{!"0xb\004\000\000", !1, !12} ; [ DW_TAG_lexical_block ] [propagate.cc] +!15 = !MDLocation(line: 7, scope: !16) +!16 = !{!"0xb\007\000\000", !1, !17} ; [ DW_TAG_lexical_block ] [propagate.cc] +!17 = !{!"0xb\006\000\000", !1, !12} ; [ DW_TAG_lexical_block ] [propagate.cc] +!18 = !MDLocation(line: 8, scope: !19) +!19 = !{!"0xb\008\000\000", !1, !20} ; [ DW_TAG_lexical_block ] [propagate.cc] +!20 = !{!"0xb\007\000\000", !1, !16} ; [ DW_TAG_lexical_block ] [propagate.cc] +!21 = !MDLocation(line: 9, scope: !19) +!22 = !MDLocation(line: 10, scope: !23) +!23 = !{!"0xb\0010\000\000", !1, !20} ; [ DW_TAG_lexical_block ] [propagate.cc] +!24 = !MDLocation(line: 11, scope: !25) +!25 = !{!"0xb\0010\000\000", !1, !23} ; [ DW_TAG_lexical_block ] [propagate.cc] +!26 = !MDLocation(line: 12, scope: !25) +!27 = !MDLocation(line: 13, scope: !25) +!28 = !MDLocation(line: 14, scope: !29) +!29 = !{!"0xb\0014\000\000", !1, !30} ; [ DW_TAG_lexical_block ] [propagate.cc] +!30 = !{!"0xb\0013\000\000", !1, !23} ; [ DW_TAG_lexical_block ] [propagate.cc] +!31 = !MDLocation(line: 15, scope: !32) +!32 = !{!"0xb\0014\000\000", !1, !29} ; [ DW_TAG_lexical_block ] [propagate.cc] +!33 = !MDLocation(line: 16, scope: !32) +!34 = !MDLocation(line: 17, scope: !32) +!35 = !MDLocation(line: 19, scope: !20) +!36 = !MDLocation(line: 21, scope: !4) +!37 = !MDLocation(line: 22, scope: !4) +!38 = !MDLocation(line: 25, scope: !7) +!39 = !MDLocation(line: 26, scope: !7) +!40 = !MDLocation(line: 27, scope: !7) +!41 = !MDLocation(line: 28, scope: !7) +!42 = !MDLocation(line: 29, scope: !7) diff --git a/test/Transforms/SampleProfile/syntax.ll b/test/Transforms/SampleProfile/syntax.ll index 53c65f44239c..ed38a175288a 100644 --- a/test/Transforms/SampleProfile/syntax.ll +++ b/test/Transforms/SampleProfile/syntax.ll @@ -1,4 +1,4 @@ -; RUN: not opt < %s -sample-profile -sample-profile-file=%S/Inputs/syntax.prof 2>&1 | FileCheck -check-prefix=NO-DEBUG %s +; RUN: opt < %s -sample-profile -sample-profile-file=%S/Inputs/syntax.prof 2>&1 | FileCheck -check-prefix=NO-DEBUG %s ; RUN: not opt < %s -sample-profile -sample-profile-file=missing.prof 2>&1 | FileCheck -check-prefix=MISSING-FILE %s ; RUN: not opt < %s -sample-profile -sample-profile-file=%S/Inputs/bad_fn_header.prof 2>&1 | FileCheck -check-prefix=BAD-FN-HEADER %s ; RUN: not opt < %s -sample-profile -sample-profile-file=%S/Inputs/bad_sample_line.prof 2>&1 | FileCheck -check-prefix=BAD-SAMPLE-LINE %s @@ -11,8 +11,8 @@ define void @empty() { entry: ret void } -; NO-DEBUG: error: No debug information found in function empty -; MISSING-FILE: error: missing.prof: +; NO-DEBUG: warning: No debug information found in function empty: Function profile not used +; MISSING-FILE: missing.prof: Could not open profile: ; BAD-FN-HEADER: error: {{.*}}bad_fn_header.prof:1: Expected 'mangled_name:NUM:NUM', found 3empty:100:BAD ; BAD-SAMPLE-LINE: error: {{.*}}bad_sample_line.prof:3: Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found 1: BAD ; BAD-LINE-VALUES: error: {{.*}}bad_line_values.prof:2: Expected 'mangled_name:NUM:NUM', found -1: 10 diff --git a/test/Transforms/ScalarRepl/debuginfo-preserved.ll b/test/Transforms/ScalarRepl/debuginfo-preserved.ll index 71bf22a61cd2..b0c459e21b10 100644 --- a/test/Transforms/ScalarRepl/debuginfo-preserved.ll +++ b/test/Transforms/ScalarRepl/debuginfo-preserved.ll @@ -17,10 +17,10 @@ entry: %b.addr = alloca i32, align 4 %c = alloca i32, align 4 store i32 %a, i32* %a.addr, align 4 - call void @llvm.dbg.declare(metadata !{i32* %a.addr}, metadata !6), !dbg !7 + call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !6, metadata !{}), !dbg !7 store i32 %b, i32* %b.addr, align 4 - call void @llvm.dbg.declare(metadata !{i32* %b.addr}, metadata !8), !dbg !9 - call void @llvm.dbg.declare(metadata !{i32* %c}, metadata !10), !dbg !12 + call void @llvm.dbg.declare(metadata i32* %b.addr, metadata !8, metadata !{}), !dbg !9 + call void @llvm.dbg.declare(metadata i32* %c, metadata !10, metadata !{}), !dbg !12 %tmp = load i32* %a.addr, align 4, !dbg !13 store i32 %tmp, i32* %c, align 4, !dbg !13 %tmp1 = load i32* %a.addr, align 4, !dbg !14 @@ -37,29 +37,29 @@ entry: ret i32 %add7, !dbg !16 } -declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!20} -!0 = metadata !{i32 786449, metadata !18, i32 12, metadata !"clang version 3.0 (trunk 131941)", i1 false, metadata !"", i32 0, metadata !19, metadata !19, metadata !17, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!1 = metadata !{i32 786478, metadata !18, metadata !2, metadata !"f", metadata !"f", metadata !"", i32 1, metadata !3, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32, i32)* @f, null, null, null, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [f] -!2 = metadata !{i32 786473, metadata !18} ; [ DW_TAG_file_type ] -!3 = metadata !{i32 786453, metadata !18, metadata !2, metadata !"", i32 0, i64 0, i64 0, i32 0, i32 0, null, metadata !4, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!4 = metadata !{metadata !5} -!5 = metadata !{i32 786468, null, metadata !0, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!6 = metadata !{i32 786689, metadata !1, metadata !"a", metadata !2, i32 16777217, metadata !5, i32 0, null} ; [ DW_TAG_arg_variable ] -!7 = metadata !{i32 1, i32 11, metadata !1, null} -!8 = metadata !{i32 786689, metadata !1, metadata !"b", metadata !2, i32 33554433, metadata !5, i32 0, null} ; [ DW_TAG_arg_variable ] -!9 = metadata !{i32 1, i32 18, metadata !1, null} -!10 = metadata !{i32 786688, metadata !11, metadata !"c", metadata !2, i32 2, metadata !5, i32 0, null} ; [ DW_TAG_auto_variable ] -!11 = metadata !{i32 786443, metadata !18, metadata !1, i32 1, i32 21, i32 0} ; [ DW_TAG_lexical_block ] -!12 = metadata !{i32 2, i32 9, metadata !11, null} -!13 = metadata !{i32 2, i32 14, metadata !11, null} -!14 = metadata !{i32 3, i32 5, metadata !11, null} -!15 = metadata !{i32 4, i32 5, metadata !11, null} -!16 = metadata !{i32 5, i32 5, metadata !11, null} -!17 = metadata !{metadata !1} -!18 = metadata !{metadata !"/d/j/debug-test.c", metadata !"/Volumes/Data/b"} -!19 = metadata !{i32 0} -!20 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x11\0012\00clang version 3.0 (trunk 131941)\000\00\000\00\000", !18, !19, !19, !17, null, null} ; [ DW_TAG_compile_unit ] +!1 = !{!"0x2e\00f\00f\00\001\000\001\000\006\00256\000\001", !18, !2, !3, null, i32 (i32, i32)* @f, null, null, null} ; [ DW_TAG_subprogram ] [line 1] [def] [f] +!2 = !{!"0x29", !18} ; [ DW_TAG_file_type ] +!3 = !{!"0x15\00\000\000\000\000\000\000", !18, !2, null, !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!4 = !{!5} +!5 = !{!"0x24\00int\000\0032\0032\000\000\005", null, !0} ; [ DW_TAG_base_type ] +!6 = !{!"0x101\00a\0016777217\000", !1, !2, !5} ; [ DW_TAG_arg_variable ] +!7 = !MDLocation(line: 1, column: 11, scope: !1) +!8 = !{!"0x101\00b\0033554433\000", !1, !2, !5} ; [ DW_TAG_arg_variable ] +!9 = !MDLocation(line: 1, column: 18, scope: !1) +!10 = !{!"0x100\00c\002\000", !11, !2, !5} ; [ DW_TAG_auto_variable ] +!11 = !{!"0xb\001\0021\000", !18, !1} ; [ DW_TAG_lexical_block ] +!12 = !MDLocation(line: 2, column: 9, scope: !11) +!13 = !MDLocation(line: 2, column: 14, scope: !11) +!14 = !MDLocation(line: 3, column: 5, scope: !11) +!15 = !MDLocation(line: 4, column: 5, scope: !11) +!16 = !MDLocation(line: 5, column: 5, scope: !11) +!17 = !{!1} +!18 = !{!"/d/j/debug-test.c", !"/Volumes/Data/b"} +!19 = !{i32 0} +!20 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/Scalarizer/basic.ll b/test/Transforms/Scalarizer/basic.ll index 1cfc0dd29017..a94cf9f61142 100644 --- a/test/Transforms/Scalarizer/basic.ll +++ b/test/Transforms/Scalarizer/basic.ll @@ -443,9 +443,9 @@ exit: ret <4 x float> %next_acc } -!0 = metadata !{ metadata !"root" } -!1 = metadata !{ metadata !"set1", metadata !0 } -!2 = metadata !{ metadata !"set2", metadata !0 } -!3 = metadata !{ metadata !3 } -!4 = metadata !{ float 4.0 } -!5 = metadata !{ i64 0, i64 8, null } +!0 = !{ !"root" } +!1 = !{ !"set1", !0 } +!2 = !{ !"set2", !0 } +!3 = !{ !3 } +!4 = !{ float 4.0 } +!5 = !{ i64 0, i64 8, null } diff --git a/test/Transforms/Scalarizer/dbginfo.ll b/test/Transforms/Scalarizer/dbginfo.ll index 546e89da80cb..ed65aaace2c4 100644 --- a/test/Transforms/Scalarizer/dbginfo.ll +++ b/test/Transforms/Scalarizer/dbginfo.ll @@ -16,9 +16,9 @@ define void @f1(<4 x i32>* nocapture %a, <4 x i32>* nocapture readonly %b, <4 x ; CHECK: %b.i1 = getelementptr i32* %b.i0, i32 1 ; CHECK: %b.i2 = getelementptr i32* %b.i0, i32 2 ; CHECK: %b.i3 = getelementptr i32* %b.i0, i32 3 -; CHECK: tail call void @llvm.dbg.value(metadata !{<4 x i32>* %a}, i64 0, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} -; CHECK: tail call void @llvm.dbg.value(metadata !{<4 x i32>* %b}, i64 0, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} -; CHECK: tail call void @llvm.dbg.value(metadata !{<4 x i32>* %c}, i64 0, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} +; CHECK: tail call void @llvm.dbg.value(metadata <4 x i32>* %a, i64 0, metadata !{{[0-9]+}}, metadata {{.*}}), !dbg !{{[0-9]+}} +; CHECK: tail call void @llvm.dbg.value(metadata <4 x i32>* %b, i64 0, metadata !{{[0-9]+}}, metadata {{.*}}), !dbg !{{[0-9]+}} +; CHECK: tail call void @llvm.dbg.value(metadata <4 x i32>* %c, i64 0, metadata !{{[0-9]+}}, metadata {{.*}}), !dbg !{{[0-9]+}} ; CHECK: %bval.i0 = load i32* %b.i0, align 16, !dbg ![[TAG1:[0-9]+]], !tbaa ![[TAG2:[0-9]+]] ; CHECK: %bval.i1 = load i32* %b.i1, align 4, !dbg ![[TAG1]], !tbaa ![[TAG2]] ; CHECK: %bval.i2 = load i32* %b.i2, align 8, !dbg ![[TAG1]], !tbaa ![[TAG2]] @@ -37,9 +37,9 @@ define void @f1(<4 x i32>* nocapture %a, <4 x i32>* nocapture readonly %b, <4 x ; CHECK: store i32 %add.i3, i32* %a.i3, align 4, !dbg ![[TAG1]], !tbaa ![[TAG2]] ; CHECK: ret void entry: - tail call void @llvm.dbg.value(metadata !{<4 x i32>* %a}, i64 0, metadata !15), !dbg !20 - tail call void @llvm.dbg.value(metadata !{<4 x i32>* %b}, i64 0, metadata !16), !dbg !20 - tail call void @llvm.dbg.value(metadata !{<4 x i32>* %c}, i64 0, metadata !17), !dbg !20 + tail call void @llvm.dbg.value(metadata <4 x i32>* %a, i64 0, metadata !15, metadata !{}), !dbg !20 + tail call void @llvm.dbg.value(metadata <4 x i32>* %b, i64 0, metadata !16, metadata !{}), !dbg !20 + tail call void @llvm.dbg.value(metadata <4 x i32>* %c, i64 0, metadata !17, metadata !{}), !dbg !20 %bval = load <4 x i32>* %b, align 16, !dbg !21, !tbaa !22 %cval = load <4 x i32>* %c, align 16, !dbg !21, !tbaa !22 %add = add <4 x i32> %bval, %cval, !dbg !21 @@ -48,7 +48,7 @@ entry: } ; Function Attrs: nounwind readnone -declare void @llvm.dbg.value(metadata, i64, metadata) #1 +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1 attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone } @@ -57,30 +57,30 @@ attributes #1 = { nounwind readnone } !llvm.module.flags = !{!18, !26} !llvm.ident = !{!19} -!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.4 (trunk 194134) (llvm/trunk 194126)", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/home/richards/llvm/build//tmp/add.c] [DW_LANG_C99] -!1 = metadata !{metadata !"/tmp/add.c", metadata !"/home/richards/llvm/build"} -!2 = metadata !{i32 0} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"f1", metadata !"f1", metadata !"", i32 3, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (<4 x i32>*, <4 x i32>*, <4 x i32>*)* @f1, null, null, metadata !14, i32 4} ; [ DW_TAG_subprogram ] [line 3] [def] [scope 4] [f] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/home/richards/llvm/build//tmp/add.c] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{null, metadata !8, metadata !8, metadata !8} -!8 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !9} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from V4SI] -!9 = metadata !{i32 786454, metadata !1, null, metadata !"V4SI", i32 1, i64 0, i64 0, i64 0, i32 0, metadata !10} ; [ DW_TAG_typedef ] [V4SI] [line 1, size 0, align 0, offset 0] [from ] -!10 = metadata !{i32 786433, null, null, metadata !"", i32 0, i64 128, i64 128, i32 0, i32 2048, metadata !11, metadata !12, i32 0, null, null, null} ; [ DW_TAG_array_type ] [line 0, size 128, align 128, offset 0] [vector] [from int] -!11 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] -!12 = metadata !{metadata !13} -!13 = metadata !{i32 786465, i64 0, i64 4} ; [ DW_TAG_subrange_type ] [0, 3] -!14 = metadata !{metadata !15, metadata !16, metadata !17} -!15 = metadata !{i32 786689, metadata !4, metadata !"a", metadata !5, i32 16777219, metadata !8, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [a] [line 3] -!16 = metadata !{i32 786689, metadata !4, metadata !"b", metadata !5, i32 33554435, metadata !8, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [b] [line 3] -!17 = metadata !{i32 786689, metadata !4, metadata !"c", metadata !5, i32 50331651, metadata !8, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [c] [line 3] -!18 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!19 = metadata !{metadata !"clang version 3.4 (trunk 194134) (llvm/trunk 194126)"} -!20 = metadata !{i32 3, i32 0, metadata !4, null} -!21 = metadata !{i32 5, i32 0, metadata !4, null} -!22 = metadata !{metadata !23, metadata !23, i64 0} -!23 = metadata !{metadata !"omnipotent char", metadata !24, i64 0} -!24 = metadata !{metadata !"Simple C/C++ TBAA"} -!25 = metadata !{i32 6, i32 0, metadata !4, null} -!26 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x11\0012\00clang version 3.4 (trunk 194134) (llvm/trunk 194126)\001\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [/home/richards/llvm/build//tmp/add.c] [DW_LANG_C99] +!1 = !{!"/tmp/add.c", !"/home/richards/llvm/build"} +!2 = !{i32 0} +!3 = !{!4} +!4 = !{!"0x2e\00f1\00f1\00\003\000\001\000\006\00256\001\004", !1, !5, !6, null, void (<4 x i32>*, <4 x i32>*, <4 x i32>*)* @f1, null, null, !14} ; [ DW_TAG_subprogram ] [line 3] [def] [scope 4] [f] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [/home/richards/llvm/build//tmp/add.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{null, !8, !8, !8} +!8 = !{!"0xf\00\000\0064\0064\000\000", null, null, !9} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from V4SI] +!9 = !{!"0x16\00V4SI\001\000\000\000\000", !1, null, !10} ; [ DW_TAG_typedef ] [V4SI] [line 1, size 0, align 0, offset 0] [from ] +!10 = !{!"0x1\00\000\00128\00128\000\002048", null, null, !11, !12, i32 0, null, null, null} ; [ DW_TAG_array_type ] [line 0, size 128, align 128, offset 0] [vector] [from int] +!11 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!12 = !{!13} +!13 = !{!"0x21\000\004"} ; [ DW_TAG_subrange_type ] [0, 3] +!14 = !{!15, !16, !17} +!15 = !{!"0x101\00a\0016777219\000", !4, !5, !8} ; [ DW_TAG_arg_variable ] [a] [line 3] +!16 = !{!"0x101\00b\0033554435\000", !4, !5, !8} ; [ DW_TAG_arg_variable ] [b] [line 3] +!17 = !{!"0x101\00c\0050331651\000", !4, !5, !8} ; [ DW_TAG_arg_variable ] [c] [line 3] +!18 = !{i32 2, !"Dwarf Version", i32 4} +!19 = !{!"clang version 3.4 (trunk 194134) (llvm/trunk 194126)"} +!20 = !MDLocation(line: 3, scope: !4) +!21 = !MDLocation(line: 5, scope: !4) +!22 = !{!23, !23, i64 0} +!23 = !{!"omnipotent char", !24, i64 0} +!24 = !{!"Simple C/C++ TBAA"} +!25 = !MDLocation(line: 6, scope: !4) +!26 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/split-gep.ll b/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/split-gep.ll index 1784171454d6..ea0d3f5673a5 100644 --- a/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/split-gep.ll +++ b/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/split-gep.ll @@ -234,3 +234,46 @@ entry: ; CHECK-LABEL: @and( ; CHECK: getelementptr [32 x [32 x float]]* @float_2d_array ; CHECK-NOT: getelementptr + +; The code that rebuilds an OR expression used to be buggy, and failed on this +; test. +define float* @shl_add_or(i64 %a, float* %ptr) { +; CHECK-LABEL: @shl_add_or( +entry: + %shl = shl i64 %a, 2 + %add = add i64 %shl, 12 + %or = or i64 %add, 1 +; CHECK: [[OR:%or[0-9]*]] = add i64 %shl, 1 + ; ((a << 2) + 12) and 1 have no common bits. Therefore, + ; SeparateConstOffsetFromGEP is able to extract the 12. + ; TODO(jingyue): We could reassociate the expression to combine 12 and 1. + %p = getelementptr float* %ptr, i64 %or +; CHECK: [[PTR:%[a-zA-Z0-9]+]] = getelementptr float* %ptr, i64 [[OR]] +; CHECK: getelementptr float* [[PTR]], i64 12 + ret float* %p +; CHECK-NEXT: ret +} + +; The source code used to be buggy in checking +; (AccumulativeByteOffset % ElementTypeSizeOfGEP == 0) +; where AccumulativeByteOffset is signed but ElementTypeSizeOfGEP is unsigned. +; The compiler would promote AccumulativeByteOffset to unsigned, causing +; unexpected results. For example, while -64 % (int64_t)24 != 0, +; -64 % (uint64_t)24 == 0. +%struct3 = type { i64, i32 } +%struct2 = type { %struct3, i32 } +%struct1 = type { i64, %struct2 } +%struct0 = type { i32, i32, i64*, [100 x %struct1] } +define %struct2* @sign_mod_unsign(%struct0* %ptr, i64 %idx) { +; CHECK-LABEL: @sign_mod_unsign( +entry: + %arrayidx = add nsw i64 %idx, -2 +; CHECK-NOT: add + %ptr2 = getelementptr inbounds %struct0* %ptr, i64 0, i32 3, i64 %arrayidx, i32 1 +; CHECK: [[PTR:%[a-zA-Z0-9]+]] = getelementptr %struct0* %ptr, i64 0, i32 3, i64 %idx, i32 1 +; CHECK: [[PTR1:%[a-zA-Z0-9]+]] = bitcast %struct2* [[PTR]] to i8* +; CHECK: getelementptr i8* [[PTR1]], i64 -64 +; CHECK: bitcast + ret %struct2* %ptr2 +; CHECK-NEXT: ret +} diff --git a/test/Transforms/SimplifyCFG/UnreachableEliminate.ll b/test/Transforms/SimplifyCFG/UnreachableEliminate.ll index e1635f491156..21428c62f531 100644 --- a/test/Transforms/SimplifyCFG/UnreachableEliminate.ll +++ b/test/Transforms/SimplifyCFG/UnreachableEliminate.ll @@ -47,7 +47,7 @@ T: } ; PR9450 -define i32 @test4(i32 %v) { +define i32 @test4(i32 %v, i32 %w) { ; CHECK: entry: ; CHECK-NEXT: switch i32 %v, label %T [ ; CHECK-NEXT: i32 3, label %V @@ -67,7 +67,54 @@ SWITCH: default: unreachable U: - ret i32 1 + ret i32 %w T: ret i32 2 } + + +;; We can either convert the following control-flow to a select or remove the +;; unreachable control flow because of the undef store of null. Make sure we do +;; the latter. + +define void @test5(i1 %cond, i8* %ptr) { + +; CHECK-LABEL: test5 +; CHECK: entry: +; CHECK-NOT: select +; CHECK: store i8 2, i8* %ptr +; CHECK: ret + +entry: + br i1 %cond, label %bb1, label %bb3 + +bb3: + br label %bb2 + +bb1: + br label %bb2 + +bb2: + %ptr.2 = phi i8* [ %ptr, %bb3 ], [ null, %bb1 ] + store i8 2, i8* %ptr.2, align 8 + ret void +} + +; CHECK-LABEL: test6 +; CHECK: entry: +; CHECK-NOT: select +; CHECK: store i8 2, i8* %ptr +; CHECK: ret + +define void @test6(i1 %cond, i8* %ptr) { +entry: + br i1 %cond, label %bb1, label %bb2 + +bb1: + br label %bb2 + +bb2: + %ptr.2 = phi i8* [ %ptr, %entry ], [ null, %bb1 ] + store i8 2, i8* %ptr.2, align 8 + ret void +} diff --git a/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll b/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll new file mode 100644 index 000000000000..22599b397ed4 --- /dev/null +++ b/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll @@ -0,0 +1,50 @@ +; RUN: opt -S -simplifycfg < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s +; rdar://17887153 +target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-darwin12.0.0" + +; When we have a covered lookup table, make sure we don't delete PHINodes that +; are cached in PHIs. +; CHECK-LABEL: @test +; CHECK: entry: +; CHECK-NEXT: sub i3 %arg, -4 +; CHECK-NEXT: zext i3 %switch.tableidx to i4 +; CHECK-NEXT: getelementptr inbounds [8 x i64]* @switch.table, i32 0, i4 %switch.tableidx.zext +; CHECK-NEXT: load i64* %switch.gep +; CHECK-NEXT: add i64 +; CHECK-NEXT: ret i64 +define i64 @test(i3 %arg) { +entry: + switch i3 %arg, label %Default [ + i3 -2, label %Label6 + i3 1, label %Label1 + i3 2, label %Label2 + i3 3, label %Label3 + i3 -4, label %Label4 + i3 -3, label %Label5 + ] + +Default: + %v1 = phi i64 [ 7, %Label6 ], [ 11, %Label5 ], [ 6, %Label4 ], [ 13, %Label3 ], [ 9, %Label2 ], [ 15, %Label1 ], [ 8, %entry ] + %v2 = phi i64 [ 0, %Label6 ], [ 0, %Label5 ], [ 0, %Label4 ], [ 0, %Label3 ], [ 0, %Label2 ], [ 0, %Label1 ], [ 0, %entry ] + %v3 = add i64 %v1, %v2 + ret i64 %v3 + +Label1: + br label %Default + +Label2: + br label %Default + +Label3: + br label %Default + +Label4: + br label %Default + +Label5: + br label %Default + +Label6: + br label %Default +} diff --git a/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll b/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll index 51ced4099ac9..22f18cd4d432 100644 --- a/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll +++ b/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll @@ -782,7 +782,6 @@ return: } ; Don't create a table with illegal type -; rdar://12779436 define i96 @illegaltype(i32 %c) { entry: switch i32 %c, label %sw.default [ @@ -856,10 +855,10 @@ return: ; CHECK: entry: ; CHECK: br i1 %{{.*}}, label %switch.hole_check, label %sw.default ; CHECK: switch.hole_check: -; CHECK-NEXT: %switch.maskindex = trunc i32 %switch.tableidx to i6 -; CHECK-NEXT: %switch.shifted = lshr i6 -17, %switch.maskindex +; CHECK-NEXT: %switch.maskindex = trunc i32 %switch.tableidx to i8 +; CHECK-NEXT: %switch.shifted = lshr i8 47, %switch.maskindex ; The mask is binary 101111. -; CHECK-NEXT: %switch.lobit = trunc i6 %switch.shifted to i1 +; CHECK-NEXT: %switch.lobit = trunc i8 %switch.shifted to i1 ; CHECK-NEXT: br i1 %switch.lobit, label %switch.lookup, label %sw.default ; CHECK-NOT: switch i32 } @@ -895,7 +894,7 @@ sw.bb1: br label %return sw.bb2: br label %return sw.default: br label %return return: - %x = phi i32 [ 3, %sw.default ], [ 5, %sw.bb2 ], [ 7, %sw.bb1 ], [ 9, %entry ] + %x = phi i32 [ 3, %sw.default ], [ 5, %sw.bb2 ], [ 7, %sw.bb1 ], [ 10, %entry ] ret i32 %x ; CHECK-LABEL: @threecases( ; CHECK-NOT: switch i32 @@ -915,8 +914,12 @@ return: %x = phi i32 [ 3, %sw.default ], [ 7, %sw.bb1 ], [ 9, %entry ] ret i32 %x ; CHECK-LABEL: @twocases( -; CHECK: switch i32 +; CHECK-NOT: switch i32 ; CHECK-NOT: @switch.table +; CHECK: %switch.selectcmp +; CHECK-NEXT: %switch.select +; CHECK-NEXT: %switch.selectcmp1 +; CHECK-NEXT: %switch.select2 } ; Don't build tables for switches with TLS variables. @@ -973,3 +976,271 @@ return: ; CHECK: switch i32 ; CHECK-NOT: @switch.table } + +; We can use linear mapping. +define i8 @linearmap1(i32 %c) { +entry: + switch i32 %c, label %sw.default [ + i32 10, label %return + i32 11, label %sw.bb1 + i32 12, label %sw.bb2 + i32 13, label %sw.bb3 + ] +sw.bb1: br label %return +sw.bb2: br label %return +sw.bb3: br label %return +sw.default: br label %return +return: + %x = phi i8 [ 3, %sw.default ], [ 3, %sw.bb3 ], [ 8, %sw.bb2 ], [ 13, %sw.bb1 ], [ 18, %entry ] + ret i8 %x +; CHECK-LABEL: @linearmap1( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i32 %c, 10 +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.idx.cast = trunc i32 %switch.tableidx to i8 +; CHECK-NEXT: %switch.idx.mult = mul i8 %switch.idx.cast, -5 +; CHECK-NEXT: %switch.offset = add i8 %switch.idx.mult, 18 +; CHECK-NEXT: ret i8 %switch.offset +} + +; Linear mapping in a different configuration. +define i32 @linearmap2(i8 %c) { +entry: + switch i8 %c, label %sw.default [ + i8 -10, label %return + i8 -11, label %sw.bb1 + i8 -12, label %sw.bb2 + i8 -13, label %sw.bb3 + ] +sw.bb1: br label %return +sw.bb2: br label %return +sw.bb3: br label %return +sw.default: br label %return +return: + %x = phi i32 [ 3, %sw.default ], [ 18, %sw.bb3 ], [ 19, %sw.bb2 ], [ 20, %sw.bb1 ], [ 21, %entry ] + ret i32 %x +; CHECK-LABEL: @linearmap2( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i8 %c, -13 +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.idx.cast = zext i8 %switch.tableidx to i32 +; CHECK-NEXT: %switch.offset = add i32 %switch.idx.cast, 18 +; CHECK-NEXT: ret i32 %switch.offset +} + +; Linear mapping with overflows. +define i8 @linearmap3(i32 %c) { +entry: + switch i32 %c, label %sw.default [ + i32 10, label %return + i32 11, label %sw.bb1 + i32 12, label %sw.bb2 + i32 13, label %sw.bb3 + ] +sw.bb1: br label %return +sw.bb2: br label %return +sw.bb3: br label %return +sw.default: br label %return +return: + %x = phi i8 [ 3, %sw.default ], [ 44, %sw.bb3 ], [ -56, %sw.bb2 ], [ 100, %sw.bb1 ], [ 0, %entry ] + ret i8 %x +; CHECK-LABEL: @linearmap3( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i32 %c, 10 +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.idx.cast = trunc i32 %switch.tableidx to i8 +; CHECK-NEXT: %switch.idx.mult = mul i8 %switch.idx.cast, 100 +; CHECK-NEXT: ret i8 %switch.idx.mult +} + +; Linear mapping with with multiplier 1 and offset 0. +define i8 @linearmap4(i32 %c) { +entry: + switch i32 %c, label %sw.default [ + i32 -2, label %return + i32 -1, label %sw.bb1 + i32 0, label %sw.bb2 + i32 1, label %sw.bb3 + ] +sw.bb1: br label %return +sw.bb2: br label %return +sw.bb3: br label %return +sw.default: br label %return +return: + %x = phi i8 [ 3, %sw.default ], [ 3, %sw.bb3 ], [ 2, %sw.bb2 ], [ 1, %sw.bb1 ], [ 0, %entry ] + ret i8 %x +; CHECK-LABEL: @linearmap4( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i32 %c, -2 +; CHECK: switch.lookup: +; CHECK-NEXT: %switch.idx.cast = trunc i32 %switch.tableidx to i8 +; CHECK-NEXT: ret i8 %switch.idx.cast +} + +; Reuse the inverted table range compare. +define i32 @reuse_cmp1(i32 %x) { +entry: + switch i32 %x, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + ] +sw.bb: br label %sw.epilog +sw.bb1: br label %sw.epilog +sw.bb2: br label %sw.epilog +sw.bb3: br label %sw.epilog +sw.default: br label %sw.epilog +sw.epilog: + %r.0 = phi i32 [ 0, %sw.default ], [ 13, %sw.bb3 ], [ 12, %sw.bb2 ], [ 11, %sw.bb1 ], [ 10, %sw.bb ] + %cmp = icmp eq i32 %r.0, 0 ; This compare can be "replaced". + br i1 %cmp, label %if.then, label %if.end +if.then: br label %return +if.end: br label %return +return: + %retval.0 = phi i32 [ 100, %if.then ], [ %r.0, %if.end ] + ret i32 %retval.0 +; CHECK-LABEL: @reuse_cmp1( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i32 %x, 0 +; CHECK-NEXT: [[C:%.+]] = icmp ult i32 %switch.tableidx, 4 +; CHECK-NEXT: %inverted.cmp = xor i1 [[C]], true +; CHECK: [[R:%.+]] = select i1 %inverted.cmp, i32 100, i32 {{.*}} +; CHECK-NEXT: ret i32 [[R]] +} + +; Reuse the table range compare. +define i32 @reuse_cmp2(i32 %x) { +entry: + switch i32 %x, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + ] +sw.bb: br label %sw.epilog +sw.bb1: br label %sw.epilog +sw.bb2: br label %sw.epilog +sw.bb3: br label %sw.epilog +sw.default: br label %sw.epilog +sw.epilog: + %r.0 = phi i32 [ 4, %sw.default ], [ 3, %sw.bb3 ], [ 2, %sw.bb2 ], [ 1, %sw.bb1 ], [ 0, %sw.bb ] + %cmp = icmp ne i32 %r.0, 4 ; This compare can be "replaced". + br i1 %cmp, label %if.then, label %if.end +if.then: br label %return +if.end: br label %return +return: + %retval.0 = phi i32 [ %r.0, %if.then ], [ 100, %if.end ] + ret i32 %retval.0 +; CHECK-LABEL: @reuse_cmp2( +; CHECK: entry: +; CHECK-NEXT: %switch.tableidx = sub i32 %x, 0 +; CHECK-NEXT: [[C:%.+]] = icmp ult i32 %switch.tableidx, 4 +; CHECK: [[R:%.+]] = select i1 [[C]], i32 {{.*}}, i32 100 +; CHECK-NEXT: ret i32 [[R]] +} + +; Cannot reuse the table range compare, because the default value is the same +; as one of the case values. +define i32 @no_reuse_cmp(i32 %x) { +entry: + switch i32 %x, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + ] +sw.bb: br label %sw.epilog +sw.bb1: br label %sw.epilog +sw.bb2: br label %sw.epilog +sw.bb3: br label %sw.epilog +sw.default: br label %sw.epilog +sw.epilog: + %r.0 = phi i32 [ 12, %sw.default ], [ 13, %sw.bb3 ], [ 12, %sw.bb2 ], [ 11, %sw.bb1 ], [ 10, %sw.bb ] + %cmp = icmp ne i32 %r.0, 0 + br i1 %cmp, label %if.then, label %if.end +if.then: br label %return +if.end: br label %return +return: + %retval.0 = phi i32 [ %r.0, %if.then ], [ 100, %if.end ] + ret i32 %retval.0 +; CHECK-LABEL: @no_reuse_cmp( +; CHECK: [[S:%.+]] = select +; CHECK-NEXT: %cmp = icmp ne i32 [[S]], 0 +; CHECK-NEXT: [[R:%.+]] = select i1 %cmp, i32 [[S]], i32 100 +; CHECK-NEXT: ret i32 [[R]] +} + +; Cannot reuse the table range compare, because the phi at the switch merge +; point is not dominated by the switch. +define i32 @no_reuse_cmp2(i32 %x, i32 %y) { +entry: + %ec = icmp ne i32 %y, 0 + br i1 %ec, label %switch.entry, label %sw.epilog +switch.entry: + switch i32 %x, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + ] +sw.bb: br label %sw.epilog +sw.bb1: br label %sw.epilog +sw.bb2: br label %sw.epilog +sw.bb3: br label %sw.epilog +sw.default: br label %sw.epilog +sw.epilog: + %r.0 = phi i32 [100, %entry], [ 0, %sw.default ], [ 13, %sw.bb3 ], [ 12, %sw.bb2 ], [ 11, %sw.bb1 ], [ 10, %sw.bb ] + %cmp = icmp eq i32 %r.0, 0 ; This compare can be "replaced". + br i1 %cmp, label %if.then, label %if.end +if.then: br label %return +if.end: br label %return +return: + %retval.0 = phi i32 [ 100, %if.then ], [ %r.0, %if.end ] + ret i32 %retval.0 +; CHECK-LABEL: @no_reuse_cmp2( +; CHECK: %r.0 = phi +; CHECK-NEXT: %cmp = icmp eq i32 %r.0, 0 +; CHECK-NEXT: [[R:%.+]] = select i1 %cmp +; CHECK-NEXT: ret i32 [[R]] +} + +define void @pr20210(i8 %x, i1 %y) { +; %z has uses outside of its BB or the phi it feeds into, +; so doing a table lookup and jumping directly to while.cond would +; cause %z to cease dominating all its uses. + +entry: + br i1 %y, label %sw, label %intermediate + +sw: + switch i8 %x, label %end [ + i8 7, label %intermediate + i8 3, label %intermediate + i8 2, label %intermediate + i8 1, label %intermediate + i8 0, label %intermediate + ] + +intermediate: + %z = zext i8 %x to i32 + br label %while.cond + +while.cond: + %i = phi i32 [ %z, %intermediate ], [ %j, %while.body ] + %b = icmp ne i32 %i, 7 + br i1 %b, label %while.body, label %while.end + +while.body: + %j = add i32 %i, 1 + br label %while.cond + +while.end: + call void @exit(i32 %z) + unreachable + +end: + ret void +; CHECK-LABEL: @pr20210 +; CHECK: switch i8 %x +} diff --git a/test/Transforms/SimplifyCFG/assume.ll b/test/Transforms/SimplifyCFG/assume.ll new file mode 100644 index 000000000000..1d1b96a58edf --- /dev/null +++ b/test/Transforms/SimplifyCFG/assume.ll @@ -0,0 +1,22 @@ +; RUN: opt -simplifycfg -S < %s | FileCheck %s + +define void @test1() { + call void @llvm.assume(i1 0) + ret void + +; CHECK-LABEL: @test1 +; CHECK-NOT: llvm.assume +; CHECK: unreachable +} + +define void @test2() { + call void @llvm.assume(i1 undef) + ret void + +; CHECK-LABEL: @test2 +; CHECK-NOT: llvm.assume +; CHECK: unreachable +} + +declare void @llvm.assume(i1) nounwind + diff --git a/test/Transforms/SimplifyCFG/basictest.ll b/test/Transforms/SimplifyCFG/basictest.ll index d6958a9c111a..5de7cc5e31d5 100644 --- a/test/Transforms/SimplifyCFG/basictest.ll +++ b/test/Transforms/SimplifyCFG/basictest.ll @@ -68,6 +68,6 @@ bb3: } declare i8 @test6g(i8*) -!0 = metadata !{metadata !1, metadata !1, i64 0} -!1 = metadata !{metadata !"foo"} -!2 = metadata !{i8 0, i8 2} +!0 = !{!1, !1, i64 0} +!1 = !{!"foo"} +!2 = !{i8 0, i8 2} diff --git a/test/Transforms/SimplifyCFG/branch-fold-dbg.ll b/test/Transforms/SimplifyCFG/branch-fold-dbg.ll index 9d8086c29769..f715a0cda93c 100644 --- a/test/Transforms/SimplifyCFG/branch-fold-dbg.ll +++ b/test/Transforms/SimplifyCFG/branch-fold-dbg.ll @@ -25,7 +25,7 @@ BB2: ; preds = %BB1 BB3: ; preds = %BB2 %6 = getelementptr inbounds [5 x %0]* @0, i32 0, i32 %0, !dbg !6 - call void @llvm.dbg.value(metadata !{%0* %6}, i64 0, metadata !7), !dbg !12 + call void @llvm.dbg.value(metadata %0* %6, i64 0, metadata !7, metadata !{}), !dbg !12 %7 = icmp eq %0* %6, null, !dbg !13 br i1 %7, label %BB5, label %BB4, !dbg !13 @@ -37,23 +37,23 @@ BB5: ; preds = %BB3, %BB2, %BB1, %E ret void, !dbg !14 } -declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone !llvm.dbg.sp = !{!0} -!0 = metadata !{i32 589870, metadata !15, metadata !1, metadata !"foo", metadata !"foo", metadata !"", i32 231, metadata !3, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (i32)* @foo, null, null, null, i32 0} ; [ DW_TAG_subprogram ] [line 231] [def] [scope 0] [foo] -!1 = metadata !{i32 589865, metadata !15} ; [ DW_TAG_file_type ] -!2 = metadata !{i32 589841, metadata !15, i32 12, metadata !"clang (trunk 129006)", i1 true, metadata !"", i32 0, metadata !4, metadata !4, null, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!3 = metadata !{i32 589845, metadata !15, metadata !1, metadata !"", i32 0, i64 0, i64 0, i32 0, i32 0, null, metadata !4, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!4 = metadata !{null} -!5 = metadata !{i32 131, i32 2, metadata !0, null} -!6 = metadata !{i32 134, i32 2, metadata !0, null} -!7 = metadata !{i32 590080, metadata !8, metadata !"bar", metadata !1, i32 232, metadata !9, i32 0} ; [ DW_TAG_auto_variable ] -!8 = metadata !{i32 589835, metadata !15, metadata !0, i32 231, i32 1, i32 3} ; [ DW_TAG_lexical_block ] -!9 = metadata !{i32 589839, null, metadata !2, metadata !"", i32 0, i64 32, i64 32, i64 0, i32 0, metadata !10} ; [ DW_TAG_pointer_type ] -!10 = metadata !{i32 589862, null, metadata !2, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, metadata !11} ; [ DW_TAG_const_type ] -!11 = metadata !{i32 589860, null, metadata !2, metadata !"unsigned int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 7} ; [ DW_TAG_base_type ] -!12 = metadata !{i32 232, i32 40, metadata !8, null} -!13 = metadata !{i32 234, i32 2, metadata !8, null} -!14 = metadata !{i32 274, i32 1, metadata !8, null} -!15 = metadata !{metadata !"a.c", metadata !"/private/tmp"} +!0 = !{!"0x2e\00foo\00foo\00\00231\000\001\000\006\00256\000\000", !15, !1, !3, null, void (i32)* @foo, null, null, null} ; [ DW_TAG_subprogram ] [line 231] [def] [scope 0] [foo] +!1 = !{!"0x29", !15} ; [ DW_TAG_file_type ] +!2 = !{!"0x11\0012\00clang (trunk 129006)\001\00\000\00\000", !15, !4, !4, null, null, null} ; [ DW_TAG_compile_unit ] +!3 = !{!"0x15\00\000\000\000\000\000\000", !15, !1, null, !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!4 = !{null} +!5 = !MDLocation(line: 131, column: 2, scope: !0) +!6 = !MDLocation(line: 134, column: 2, scope: !0) +!7 = !{!"0x100\00bar\00232\000", !8, !1, !9} ; [ DW_TAG_auto_variable ] +!8 = !{!"0xb\00231\001\003", !15, !0} ; [ DW_TAG_lexical_block ] +!9 = !{!"0xf\00\000\0032\0032\000\000", null, !2, !10} ; [ DW_TAG_pointer_type ] +!10 = !{!"0x26\00\000\000\000\000\000", null, !2, !11} ; [ DW_TAG_const_type ] +!11 = !{!"0x24\00unsigned int\000\0032\0032\000\000\007", null, !2} ; [ DW_TAG_base_type ] +!12 = !MDLocation(line: 232, column: 40, scope: !8) +!13 = !MDLocation(line: 234, column: 2, scope: !8) +!14 = !MDLocation(line: 274, column: 1, scope: !8) +!15 = !{!"a.c", !"/private/tmp"} diff --git a/test/Transforms/SimplifyCFG/branch-fold-threshold.ll b/test/Transforms/SimplifyCFG/branch-fold-threshold.ll new file mode 100644 index 000000000000..878c0a4837ae --- /dev/null +++ b/test/Transforms/SimplifyCFG/branch-fold-threshold.ll @@ -0,0 +1,28 @@ +; RUN: opt %s -simplifycfg -S | FileCheck %s --check-prefix=NORMAL +; RUN: opt %s -simplifycfg -S -bonus-inst-threshold=2 | FileCheck %s --check-prefix=AGGRESSIVE + +define i32 @foo(i32 %a, i32 %b, i32 %c, i32 %d, i32* %input) { +; NORMAL-LABEL: @foo( +; AGGRESSIVE-LABEL: @foo( +entry: + %cmp = icmp sgt i32 %d, 3 + br i1 %cmp, label %cond.end, label %lor.lhs.false +; NORMAL: br i1 +; AGGRESSIVE: br i1 + +lor.lhs.false: + %mul = shl i32 %c, 1 + %add = add nsw i32 %mul, %a + %cmp1 = icmp slt i32 %add, %b + br i1 %cmp1, label %cond.false, label %cond.end +; NORMAL: br i1 +; AGGRESSIVE-NOT: br i1 + +cond.false: + %0 = load i32* %input, align 4 + br label %cond.end + +cond.end: + %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ] + ret i32 %cond +} diff --git a/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll b/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll index 0547fa972017..869ce099d075 100644 --- a/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll +++ b/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll @@ -1,8 +1,8 @@ ; RUN: opt -simplifycfg -S < %s | FileCheck %s define i32 @foo(i32 %i) nounwind ssp { - call void @llvm.dbg.value(metadata !{i32 %i}, i64 0, metadata !6), !dbg !7 - call void @llvm.dbg.value(metadata !8, i64 0, metadata !9), !dbg !11 + call void @llvm.dbg.value(metadata i32 %i, i64 0, metadata !6, metadata !{}), !dbg !7 + call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !9, metadata !{}), !dbg !11 %1 = icmp ne i32 %i, 0, !dbg !12 ;CHECK: call i32 (...)* @bar() ;CHECK-NEXT: llvm.dbg.value @@ -10,12 +10,12 @@ define i32 @foo(i32 %i) nounwind ssp { ; <label>:2 ; preds = %0 %3 = call i32 (...)* @bar(), !dbg !13 - call void @llvm.dbg.value(metadata !{i32 %3}, i64 0, metadata !9), !dbg !13 + call void @llvm.dbg.value(metadata i32 %3, i64 0, metadata !9, metadata !{}), !dbg !13 br label %6, !dbg !15 ; <label>:4 ; preds = %0 %5 = call i32 (...)* @bar(), !dbg !16 - call void @llvm.dbg.value(metadata !{i32 %5}, i64 0, metadata !9), !dbg !16 + call void @llvm.dbg.value(metadata i32 %5, i64 0, metadata !9, metadata !{}), !dbg !16 br label %6, !dbg !18 ; <label>:6 ; preds = %4, %2 @@ -23,34 +23,34 @@ define i32 @foo(i32 %i) nounwind ssp { ret i32 %k.0, !dbg !19 } -declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone declare i32 @bar(...) -declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone !llvm.module.flags = !{!21} !llvm.dbg.sp = !{!0} -!0 = metadata !{i32 589870, metadata !20, metadata !1, metadata !"foo", metadata !"foo", metadata !"", i32 2, metadata !3, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32)* @foo, null, null, null, i32 0} ; [ DW_TAG_subprogram ] [line 2] [def] [scope 0] [foo] -!1 = metadata !{i32 589865, metadata !20} ; [ DW_TAG_file_type ] -!2 = metadata !{i32 589841, metadata !20, i32 12, metadata !"clang", i1 true, metadata !"", i32 0, metadata !8, metadata !8, null, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!3 = metadata !{i32 589845, metadata !20, metadata !1, metadata !"", i32 0, i64 0, i64 0, i32 0, i32 0, null, metadata !4, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!4 = metadata !{metadata !5} -!5 = metadata !{i32 589860, null, metadata !2, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!6 = metadata !{i32 590081, metadata !0, metadata !"i", metadata !1, i32 16777218, metadata !5, i32 0} ; [ DW_TAG_arg_variable ] -!7 = metadata !{i32 2, i32 13, metadata !0, null} -!8 = metadata !{i32 0} -!9 = metadata !{i32 590080, metadata !10, metadata !"k", metadata !1, i32 3, metadata !5, i32 0} ; [ DW_TAG_auto_variable ] -!10 = metadata !{i32 589835, metadata !20, metadata !0, i32 2, i32 16, i32 0} ; [ DW_TAG_lexical_block ] -!11 = metadata !{i32 3, i32 12, metadata !10, null} -!12 = metadata !{i32 4, i32 3, metadata !10, null} -!13 = metadata !{i32 5, i32 5, metadata !14, null} -!14 = metadata !{i32 589835, metadata !20, metadata !10, i32 4, i32 10, i32 1} ; [ DW_TAG_lexical_block ] -!15 = metadata !{i32 6, i32 3, metadata !14, null} -!16 = metadata !{i32 7, i32 5, metadata !17, null} -!17 = metadata !{i32 589835, metadata !20, metadata !10, i32 6, i32 10, i32 2} ; [ DW_TAG_lexical_block ] -!18 = metadata !{i32 8, i32 3, metadata !17, null} -!19 = metadata !{i32 9, i32 3, metadata !10, null} -!20 = metadata !{metadata !"b.c", metadata !"/private/tmp"} -!21 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x2e\00foo\00foo\00\002\000\001\000\006\00256\000\000", !20, !1, !3, null, i32 (i32)* @foo, null, null, null} ; [ DW_TAG_subprogram ] [line 2] [def] [scope 0] [foo] +!1 = !{!"0x29", !20} ; [ DW_TAG_file_type ] +!2 = !{!"0x11\0012\00clang\001\00\000\00\000", !20, !8, !8, null, null, null} ; [ DW_TAG_compile_unit ] +!3 = !{!"0x15\00\000\000\000\000\000\000", !20, !1, null, !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!4 = !{!5} +!5 = !{!"0x24\00int\000\0032\0032\000\000\005", null, !2} ; [ DW_TAG_base_type ] +!6 = !{!"0x101\00i\0016777218\000", !0, !1, !5} ; [ DW_TAG_arg_variable ] +!7 = !MDLocation(line: 2, column: 13, scope: !0) +!8 = !{i32 0} +!9 = !{!"0x100\00k\003\000", !10, !1, !5} ; [ DW_TAG_auto_variable ] +!10 = !{!"0xb\002\0016\000", !20, !0} ; [ DW_TAG_lexical_block ] +!11 = !MDLocation(line: 3, column: 12, scope: !10) +!12 = !MDLocation(line: 4, column: 3, scope: !10) +!13 = !MDLocation(line: 5, column: 5, scope: !14) +!14 = !{!"0xb\004\0010\001", !20, !10} ; [ DW_TAG_lexical_block ] +!15 = !MDLocation(line: 6, column: 3, scope: !14) +!16 = !MDLocation(line: 7, column: 5, scope: !17) +!17 = !{!"0xb\006\0010\002", !20, !10} ; [ DW_TAG_lexical_block ] +!18 = !MDLocation(line: 8, column: 3, scope: !17) +!19 = !MDLocation(line: 9, column: 3, scope: !10) +!20 = !{!"b.c", !"/private/tmp"} +!21 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/SimplifyCFG/hoist-with-range.ll b/test/Transforms/SimplifyCFG/hoist-with-range.ll new file mode 100644 index 000000000000..7ca3ff247dc8 --- /dev/null +++ b/test/Transforms/SimplifyCFG/hoist-with-range.ll @@ -0,0 +1,20 @@ +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +define void @foo(i1 %c, i8* %p) { +; CHECK: if: +; CHECK-NEXT: load i8* %p, !range !0 +; CHECK: !0 = !{i8 0, i8 1, i8 3, i8 5} +if: + br i1 %c, label %then, label %else +then: + %t = load i8* %p, !range !0 + br label %out +else: + %e = load i8* %p, !range !1 + br label %out +out: + ret void +} + +!0 = !{ i8 0, i8 1 } +!1 = !{ i8 3, i8 5 } diff --git a/test/Transforms/SimplifyCFG/lifetime.ll b/test/Transforms/SimplifyCFG/lifetime.ll index b79422172530..7c66be529500 100644 --- a/test/Transforms/SimplifyCFG/lifetime.ll +++ b/test/Transforms/SimplifyCFG/lifetime.ll @@ -1,11 +1,11 @@ ; RUN: opt < %s -simplifycfg -S | FileCheck %s -; Test that a lifetime intrinsic doesn't prevent us from simplifying this. +; Test that a lifetime intrinsic isn't removed because that would change semantics ; CHECK: foo ; CHECK: entry: -; CHECK-NOT: bb0: -; CHECK-NOT: bb1: +; CHECK: bb0: +; CHECK: bb1: ; CHECK: ret define void @foo(i1 %x) { entry: diff --git a/test/Transforms/SimplifyCFG/preserve-branchweights-partial.ll b/test/Transforms/SimplifyCFG/preserve-branchweights-partial.ll index 8cc07e39a180..b2b384112af8 100644 --- a/test/Transforms/SimplifyCFG/preserve-branchweights-partial.ll +++ b/test/Transforms/SimplifyCFG/preserve-branchweights-partial.ll @@ -34,4 +34,4 @@ if.end: ret void } -!0 = metadata !{metadata !"branch_weights", i32 1, i32 0} +!0 = !{!"branch_weights", i32 1, i32 0} diff --git a/test/Transforms/SimplifyCFG/preserve-branchweights-switch-create.ll b/test/Transforms/SimplifyCFG/preserve-branchweights-switch-create.ll index 941f5ad9d5b6..32a30c3cab4f 100644 --- a/test/Transforms/SimplifyCFG/preserve-branchweights-switch-create.ll +++ b/test/Transforms/SimplifyCFG/preserve-branchweights-switch-create.ll @@ -129,12 +129,12 @@ sw.epilog: ret void } -!0 = metadata !{metadata !"branch_weights", i32 64, i32 4} -!1 = metadata !{metadata !"branch_weights", i32 4, i32 64} -; CHECK: !0 = metadata !{metadata !"branch_weights", i32 256, i32 4352, i32 16} -!2 = metadata !{metadata !"branch_weights", i32 4, i32 4, i32 8} -!3 = metadata !{metadata !"branch_weights", i32 8, i32 8, i32 4} -; CHECK: !1 = metadata !{metadata !"branch_weights", i32 32, i32 48, i32 96, i32 16} -!4 = metadata !{metadata !"branch_weights", i32 7, i32 6, i32 4, i32 3} -!5 = metadata !{metadata !"branch_weights", i32 17, i32 13, i32 9} -; CHECK: !3 = metadata !{metadata !"branch_weights", i32 7, i32 3, i32 4, i32 6} +!0 = !{!"branch_weights", i32 64, i32 4} +!1 = !{!"branch_weights", i32 4, i32 64} +; CHECK: !0 = !{!"branch_weights", i32 256, i32 4352, i32 16} +!2 = !{!"branch_weights", i32 4, i32 4, i32 8} +!3 = !{!"branch_weights", i32 8, i32 8, i32 4} +; CHECK: !1 = !{!"branch_weights", i32 32, i32 48, i32 96, i32 16} +!4 = !{!"branch_weights", i32 7, i32 6, i32 4, i32 3} +!5 = !{!"branch_weights", i32 17, i32 13, i32 9} +; CHECK: !3 = !{!"branch_weights", i32 7, i32 3, i32 4, i32 6} diff --git a/test/Transforms/SimplifyCFG/preserve-branchweights.ll b/test/Transforms/SimplifyCFG/preserve-branchweights.ll index bdd25ba80585..7802a0593574 100644 --- a/test/Transforms/SimplifyCFG/preserve-branchweights.ll +++ b/test/Transforms/SimplifyCFG/preserve-branchweights.ll @@ -364,29 +364,29 @@ for.exit: ret void } -!0 = metadata !{metadata !"branch_weights", i32 3, i32 5} -!1 = metadata !{metadata !"branch_weights", i32 1, i32 1} -!2 = metadata !{metadata !"branch_weights", i32 1, i32 2} -!3 = metadata !{metadata !"branch_weights", i32 4, i32 3, i32 2, i32 1} -!4 = metadata !{metadata !"branch_weights", i32 4, i32 3, i32 2, i32 1} -!5 = metadata !{metadata !"branch_weights", i32 7, i32 6, i32 5} -!6 = metadata !{metadata !"branch_weights", i32 1, i32 3} -!7 = metadata !{metadata !"branch_weights", i32 33, i32 9, i32 8, i32 7} -!8 = metadata !{metadata !"branch_weights", i32 33, i32 9, i32 8} -!9 = metadata !{metadata !"branch_weights", i32 7, i32 6} -!10 = metadata !{metadata !"branch_weights", i32 672646, i32 21604207} -!11 = metadata !{metadata !"branch_weights", i32 6960, i32 21597248} - -; CHECK: !0 = metadata !{metadata !"branch_weights", i32 5, i32 11} -; CHECK: !1 = metadata !{metadata !"branch_weights", i32 1, i32 5} -; CHECK: !2 = metadata !{metadata !"branch_weights", i32 7, i32 1, i32 2} -; CHECK: !3 = metadata !{metadata !"branch_weights", i32 49, i32 12, i32 24, i32 35} -; CHECK: !4 = metadata !{metadata !"branch_weights", i32 11, i32 5} -; CHECK: !5 = metadata !{metadata !"branch_weights", i32 17, i32 15} -; CHECK: !6 = metadata !{metadata !"branch_weights", i32 9, i32 7} -; CHECK: !7 = metadata !{metadata !"branch_weights", i32 17, i32 9, i32 8, i32 7, i32 17} -; CHECK: !8 = metadata !{metadata !"branch_weights", i32 24, i32 33} -; CHECK: !9 = metadata !{metadata !"branch_weights", i32 8, i32 33} +!0 = !{!"branch_weights", i32 3, i32 5} +!1 = !{!"branch_weights", i32 1, i32 1} +!2 = !{!"branch_weights", i32 1, i32 2} +!3 = !{!"branch_weights", i32 4, i32 3, i32 2, i32 1} +!4 = !{!"branch_weights", i32 4, i32 3, i32 2, i32 1} +!5 = !{!"branch_weights", i32 7, i32 6, i32 5} +!6 = !{!"branch_weights", i32 1, i32 3} +!7 = !{!"branch_weights", i32 33, i32 9, i32 8, i32 7} +!8 = !{!"branch_weights", i32 33, i32 9, i32 8} +!9 = !{!"branch_weights", i32 7, i32 6} +!10 = !{!"branch_weights", i32 672646, i32 21604207} +!11 = !{!"branch_weights", i32 6960, i32 21597248} + +; CHECK: !0 = !{!"branch_weights", i32 5, i32 11} +; CHECK: !1 = !{!"branch_weights", i32 1, i32 5} +; CHECK: !2 = !{!"branch_weights", i32 7, i32 1, i32 2} +; CHECK: !3 = !{!"branch_weights", i32 49, i32 12, i32 24, i32 35} +; CHECK: !4 = !{!"branch_weights", i32 11, i32 5} +; CHECK: !5 = !{!"branch_weights", i32 17, i32 15} +; CHECK: !6 = !{!"branch_weights", i32 9, i32 7} +; CHECK: !7 = !{!"branch_weights", i32 17, i32 9, i32 8, i32 7, i32 17} +; CHECK: !8 = !{!"branch_weights", i32 24, i32 33} +; CHECK: !9 = !{!"branch_weights", i32 8, i32 33} ;; The false weight prints out as a negative integer here, but inside llvm, we ;; treat the weight as an unsigned integer. -; CHECK: !10 = metadata !{metadata !"branch_weights", i32 112017436, i32 -735157296} +; CHECK: !10 = !{!"branch_weights", i32 112017436, i32 -735157296} diff --git a/test/Transforms/SimplifyCFG/sink-common-code.ll b/test/Transforms/SimplifyCFG/sink-common-code.ll index 28d727938288..cdb6ed29d850 100644 --- a/test/Transforms/SimplifyCFG/sink-common-code.ll +++ b/test/Transforms/SimplifyCFG/sink-common-code.ll @@ -4,7 +4,7 @@ define zeroext i1 @test1(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks) { entry: br i1 %flag, label %if.then, label %if.else -; CHECK: test1 +; CHECK-LABEL: test1 ; CHECK: add ; CHECK: select ; CHECK: icmp @@ -30,7 +30,7 @@ define zeroext i1 @test2(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks) { entry: br i1 %flag, label %if.then, label %if.else -; CHECK: test2 +; CHECK-LABEL: test2 ; CHECK: add ; CHECK: select ; CHECK: icmp @@ -51,3 +51,33 @@ if.end: %tobool4 = icmp ne i8 %obeys.0, 0 ret i1 %tobool4 } + +declare i32 @foo(i32, i32) nounwind readnone + +define i32 @test3(i1 zeroext %flag, i32 %x, i32 %y) { +entry: + br i1 %flag, label %if.then, label %if.else + +if.then: + %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone + %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone + br label %if.end + +if.else: + %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone + %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone + br label %if.end + +if.end: + %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ] + %yy = phi i32 [ %y0, %if.then ], [ %y1, %if.else ] + %ret = add i32 %xx, %yy + ret i32 %ret +} + +; CHECK-LABEL: test3 +; CHECK: select +; CHECK: call +; CHECK: call +; CHECK: add +; CHECK-NOT: br diff --git a/test/Transforms/SimplifyCFG/speculate-math.ll b/test/Transforms/SimplifyCFG/speculate-math.ll index fa7976d0689f..0ba93d29117a 100644 --- a/test/Transforms/SimplifyCFG/speculate-math.ll +++ b/test/Transforms/SimplifyCFG/speculate-math.ll @@ -3,6 +3,9 @@ declare float @llvm.sqrt.f32(float) nounwind readonly declare float @llvm.fma.f32(float, float, float) nounwind readonly declare float @llvm.fmuladd.f32(float, float, float) nounwind readonly +declare float @llvm.fabs.f32(float) nounwind readonly +declare float @llvm.minnum.f32(float, float) nounwind readonly +declare float @llvm.maxnum.f32(float, float) nounwind readonly ; CHECK-LABEL: @sqrt_test( ; CHECK: select @@ -21,6 +24,22 @@ test_sqrt.exit: ; preds = %cond.else.i, %entry ret void } +; CHECK-LABEL: @fabs_test( +; CHECK: select +define void @fabs_test(float addrspace(1)* noalias nocapture %out, float %a) nounwind { +entry: + %cmp.i = fcmp olt float %a, 0.000000e+00 + br i1 %cmp.i, label %test_fabs.exit, label %cond.else.i + +cond.else.i: ; preds = %entry + %0 = tail call float @llvm.fabs.f32(float %a) nounwind readnone + br label %test_fabs.exit + +test_fabs.exit: ; preds = %cond.else.i, %entry + %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ] + store float %cond.i, float addrspace(1)* %out, align 4 + ret void +} ; CHECK-LABEL: @fma_test( ; CHECK: select @@ -56,3 +75,36 @@ test_fmuladd.exit: ; preds = %cond.else.i, %en ret void } +; CHECK-LABEL: @minnum_test( +; CHECK: select +define void @minnum_test(float addrspace(1)* noalias nocapture %out, float %a, float %b) nounwind { +entry: + %cmp.i = fcmp olt float %a, 0.000000e+00 + br i1 %cmp.i, label %test_minnum.exit, label %cond.else.i + +cond.else.i: ; preds = %entry + %0 = tail call float @llvm.minnum.f32(float %a, float %b) nounwind readnone + br label %test_minnum.exit + +test_minnum.exit: ; preds = %cond.else.i, %entry + %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ] + store float %cond.i, float addrspace(1)* %out, align 4 + ret void +} + +; CHECK-LABEL: @maxnum_test( +; CHECK: select +define void @maxnum_test(float addrspace(1)* noalias nocapture %out, float %a, float %b) nounwind { +entry: + %cmp.i = fcmp olt float %a, 0.000000e+00 + br i1 %cmp.i, label %test_maxnum.exit, label %cond.else.i + +cond.else.i: ; preds = %entry + %0 = tail call float @llvm.maxnum.f32(float %a, float %b) nounwind readnone + br label %test_maxnum.exit + +test_maxnum.exit: ; preds = %cond.else.i, %entry + %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ] + store float %cond.i, float addrspace(1)* %out, align 4 + ret void +} diff --git a/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll b/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll new file mode 100644 index 000000000000..8bf2b04520b9 --- /dev/null +++ b/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll @@ -0,0 +1,50 @@ +; RUN: opt %s -simplifycfg -S | FileCheck %s + +declare i32 @f(i32) + +define i32 @basic(i32 %x) { +; CHECK-LABEL: @basic +; CHECK: x.off = add i32 %x, -5 +; CHECK: %switch = icmp ult i32 %x.off, 3 +; CHECK: br i1 %switch, label %a, label %default + +entry: + switch i32 %x, label %default [ + i32 5, label %a + i32 6, label %a + i32 7, label %a + ] +default: + %0 = call i32 @f(i32 0) + ret i32 %0 +a: + %1 = call i32 @f(i32 1) + ret i32 %1 +} + + +define i32 @unreachable(i32 %x) { +; CHECK-LABEL: @unreachable +; CHECK: x.off = add i32 %x, -5 +; CHECK: %switch = icmp ult i32 %x.off, 3 +; CHECK: br i1 %switch, label %a, label %b + +entry: + switch i32 %x, label %unreachable [ + i32 5, label %a + i32 6, label %a + i32 7, label %a + i32 10, label %b + i32 20, label %b + i32 30, label %b + i32 40, label %b + ] +unreachable: + unreachable +a: + %0 = call i32 @f(i32 0) + ret i32 %0 +b: + %1 = call i32 @f(i32 1) + ret i32 %1 +} diff --git a/test/Transforms/SimplifyCFG/switch-to-br.ll b/test/Transforms/SimplifyCFG/switch-to-br.ll new file mode 100644 index 000000000000..01484cda98b0 --- /dev/null +++ b/test/Transforms/SimplifyCFG/switch-to-br.ll @@ -0,0 +1,64 @@ +; RUN: opt %s -simplifycfg -S | FileCheck %s + +declare i32 @f(i32) + +define i32 @basic(i32 %x) { +; CHECK-LABEL: @basic +; CHECK-LABEL: entry: +; CHECK-NEXT: call i32 @f(i32 0) +; CHECK-NEXT: ret i32 %0 + +entry: + switch i32 %x, label %default [ + i32 5, label %default + i32 6, label %default + i32 7, label %default + ] +default: + %0 = call i32 @f(i32 0) + ret i32 %0 +} + + +define i32 @constant() { +; CHECK-LABEL: @constant +; CHECK-LABEL: entry: +; CHECK-NEXT: call i32 @f(i32 1) +; CHECK-NEXT: ret i32 %0 + +entry: + switch i32 42, label %default [ + i32 41, label %default + i32 42, label %a + i32 43, label %b + ] +default: + %0 = call i32 @f(i32 0) + ret i32 %0 +a: + %1 = call i32 @f(i32 1) + ret i32 %1 +b: + %2 = call i32 @f(i32 2) + ret i32 %2 +} + + +define i32 @unreachable(i32 %x) { +; CHECK-LABEL: @unreachable +; CHECK-LABEL: entry: +; CHECK-NEXT: call i32 @f(i32 0) +; CHECK-NEXT: ret i32 %0 + +entry: + switch i32 %x, label %unreachable [ + i32 5, label %a + i32 6, label %a + i32 7, label %a + ] +unreachable: + unreachable +a: + %0 = call i32 @f(i32 0) + ret i32 %0 +} diff --git a/test/Transforms/SimplifyCFG/switch-to-select-multiple-edge-per-block-phi.ll b/test/Transforms/SimplifyCFG/switch-to-select-multiple-edge-per-block-phi.ll new file mode 100644 index 000000000000..ddf5d1f06ce7 --- /dev/null +++ b/test/Transforms/SimplifyCFG/switch-to-select-multiple-edge-per-block-phi.ll @@ -0,0 +1,40 @@ +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +; a, b; +; fn1() { +; if (b) +; if (a == 0 || a == 5) +; return a; +; return 0; +; } + +; Checking that we handle correctly the case when we have a switch +; branching multiple times to the same block + +@b = common global i32 0, align 4 +@a = common global i32 0, align 4 + +; Function Attrs: nounwind +define i32 @fn1() { +; CHECK-LABEL: @fn1 +; CHECK: %switch.selectcmp1 = icmp eq i32 %1, 5 +; CHECK: %switch.select2 = select i1 %switch.selectcmp1, i32 5, i32 %switch.select +entry: + %0 = load i32* @b, align 4 + %tobool = icmp eq i32 %0, 0 + br i1 %tobool, label %if.end3, label %if.then + +if.then: + %1 = load i32* @a, align 4 + switch i32 %1, label %if.end3 [ + i32 5, label %return + i32 0, label %return + ] + +if.end3: + br label %return + +return: + %retval.0 = phi i32 [ 0, %if.end3 ], [ %1, %if.then ], [ %1, %if.then ] + ret i32 %retval.0 +} diff --git a/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll b/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll new file mode 100644 index 000000000000..69f97e5f9f9f --- /dev/null +++ b/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll @@ -0,0 +1,72 @@ +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +; int foo1_with_default(int a) { +; switch(a) { +; case 10: +; return 10; +; case 20: +; return 2; +; } +; return 4; +; } + +define i32 @foo1_with_default(i32 %a) { +; CHECK-LABEL: @foo1_with_default +; CHECK: %switch.selectcmp = icmp eq i32 %a, 20 +; CHECK-NEXT: %switch.select = select i1 %switch.selectcmp, i32 2, i32 4 +; CHECK-NEXT: %switch.selectcmp1 = icmp eq i32 %a, 10 +; CHECK-NEXT: %switch.select2 = select i1 %switch.selectcmp1, i32 10, i32 %switch.select +entry: + switch i32 %a, label %sw.epilog [ + i32 10, label %sw.bb + i32 20, label %sw.bb1 + ] + +sw.bb: + br label %return + +sw.bb1: + br label %return + +sw.epilog: + br label %return + +return: + %retval.0 = phi i32 [ 4, %sw.epilog ], [ 2, %sw.bb1 ], [ 10, %sw.bb ] + ret i32 %retval.0 +} + +; int foo1_without_default(int a) { +; switch(a) { +; case 10: +; return 10; +; case 20: +; return 2; +; } +; __builtin_unreachable(); +; } + +define i32 @foo1_without_default(i32 %a) { +; CHECK-LABEL: @foo1_without_default +; CHECK: %switch.selectcmp = icmp eq i32 %a, 10 +; CHECK-NEXT: %switch.select = select i1 %switch.selectcmp, i32 10, i32 2 +; CHECK-NOT: %switch.selectcmp1 +entry: + switch i32 %a, label %sw.epilog [ + i32 10, label %sw.bb + i32 20, label %sw.bb1 + ] + +sw.bb: + br label %return + +sw.bb1: + br label %return + +sw.epilog: + unreachable + +return: + %retval.0 = phi i32 [ 2, %sw.bb1 ], [ 10, %sw.bb ] + ret i32 %retval.0 +} diff --git a/test/Transforms/SimplifyCFG/trap-debugloc.ll b/test/Transforms/SimplifyCFG/trap-debugloc.ll index 3b449cb000ab..24a286fd9735 100644 --- a/test/Transforms/SimplifyCFG/trap-debugloc.ll +++ b/test/Transforms/SimplifyCFG/trap-debugloc.ll @@ -11,14 +11,14 @@ define void @foo() nounwind ssp { !llvm.module.flags = !{!10} !llvm.dbg.sp = !{!0} -!0 = metadata !{i32 589870, metadata !8, metadata !1, metadata !"foo", metadata !"foo", metadata !"", i32 3, metadata !3, i1 false, i1 true, i32 0, i32 0, null, i32 0, i1 false, void ()* @foo, null, null, null, i32 0} ; [ DW_TAG_subprogram ] [line 3] [def] [scope 0] [foo] -!1 = metadata !{i32 589865, metadata !8} ; [ DW_TAG_file_type ] -!2 = metadata !{i32 589841, metadata !8, i32 12, metadata !"Apple clang version 3.0 (tags/Apple/clang-206.1) (based on LLVM 3.0svn)", i1 true, metadata !"", i32 0, metadata !4, metadata !4, metadata !9, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!3 = metadata !{i32 589845, metadata !8, metadata !1, metadata !"", i32 0, i64 0, i64 0, i32 0, i32 0, null, metadata !4, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!4 = metadata !{null} -!5 = metadata !{i32 4, i32 2, metadata !6, null} -!6 = metadata !{i32 589835, metadata !8, metadata !0, i32 3, i32 12, i32 0} ; [ DW_TAG_lexical_block ] -!7 = metadata !{i32 5, i32 1, metadata !6, null} -!8 = metadata !{metadata !"foo.c", metadata !"/private/tmp"} -!9 = metadata !{metadata !0} -!10 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x2e\00foo\00foo\00\003\000\001\000\006\000\000\000", !8, !1, !3, null, void ()* @foo, null, null, null} ; [ DW_TAG_subprogram ] [line 3] [def] [scope 0] [foo] +!1 = !{!"0x29", !8} ; [ DW_TAG_file_type ] +!2 = !{!"0x11\0012\00Apple clang version 3.0 (tags/Apple/clang-206.1) (based on LLVM 3.0svn)\001\00\000\00\000", !8, !4, !4, !9, null, null} ; [ DW_TAG_compile_unit ] +!3 = !{!"0x15\00\000\000\000\000\000\000", !8, !1, null, !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!4 = !{null} +!5 = !MDLocation(line: 4, column: 2, scope: !6) +!6 = !{!"0xb\003\0012\000", !8, !0} ; [ DW_TAG_lexical_block ] +!7 = !MDLocation(line: 5, column: 1, scope: !6) +!8 = !{!"foo.c", !"/private/tmp"} +!9 = !{!0} +!10 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/SimplifyCFG/volatile-phioper.ll b/test/Transforms/SimplifyCFG/volatile-phioper.ll index 1ef3a7ce59b3..6367451433c1 100644 --- a/test/Transforms/SimplifyCFG/volatile-phioper.ll +++ b/test/Transforms/SimplifyCFG/volatile-phioper.ll @@ -45,4 +45,4 @@ attributes #0 = { nounwind ssp uwtable "fp-contract-model"="standard" "no-frame- attributes #1 = { "fp-contract-model"="standard" "no-frame-pointer-elim" "no-frame-pointer-elim-non-leaf" "relocation-model"="pic" "ssp-buffers-size"="8" } attributes #2 = { nounwind } -!0 = metadata !{i32 1039} +!0 = !{i32 1039} diff --git a/test/Transforms/StripSymbols/2010-06-30-StripDebug.ll b/test/Transforms/StripSymbols/2010-06-30-StripDebug.ll index 5353744824dc..f2c705a317af 100644 --- a/test/Transforms/StripSymbols/2010-06-30-StripDebug.ll +++ b/test/Transforms/StripSymbols/2010-06-30-StripDebug.ll @@ -6,11 +6,11 @@ define void @foo() nounwind readnone optsize ssp { entry: - tail call void @llvm.dbg.value(metadata !9, i64 0, metadata !5), !dbg !10 + tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !5, metadata !{}), !dbg !10 ret void, !dbg !11 } -declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone !llvm.dbg.cu = !{!2} !llvm.module.flags = !{!13} @@ -18,17 +18,17 @@ declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone !llvm.dbg.lv.foo = !{!5} !llvm.dbg.gv = !{!8} -!0 = metadata !{i32 524334, metadata !12, metadata !1, metadata !"foo", metadata !"foo", metadata !"foo", i32 2, metadata !3, i1 false, i1 true, i32 0, i32 0, null, i1 false, i1 true, void ()* @foo, null, null, null, i32 0} ; [ DW_TAG_subprogram ] -!1 = metadata !{i32 524329, metadata !12} ; [ DW_TAG_file_type ] -!2 = metadata !{i32 524305, metadata !12, i32 1, metadata !"4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", i1 true, metadata !"", i32 0, metadata !4, metadata !4, null, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!3 = metadata !{i32 524309, metadata !12, metadata !1, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !4, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!4 = metadata !{null} -!5 = metadata !{i32 524544, metadata !6, metadata !"y", metadata !1, i32 3, metadata !7} ; [ DW_TAG_auto_variable ] -!6 = metadata !{i32 524299, metadata !12, metadata !0, i32 2, i32 0, i32 0} ; [ DW_TAG_lexical_block ] -!7 = metadata !{i32 524324, metadata !12, metadata !1, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!8 = metadata !{i32 524340, i32 0, metadata !1, metadata !"x", metadata !"x", metadata !"", metadata !1, i32 1, metadata !7, i1 false, i1 true, i32* @x} ; [ DW_TAG_variable ] -!9 = metadata !{i32 0} -!10 = metadata !{i32 3, i32 0, metadata !6, null} -!11 = metadata !{i32 4, i32 0, metadata !6, null} -!12 = metadata !{metadata !"b.c", metadata !"/tmp"} -!13 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x2e\00foo\00foo\00foo\002\000\001\000\006\000\001\000", !12, !1, !3, null, void ()* @foo, null, null, null} ; [ DW_TAG_subprogram ] +!1 = !{!"0x29", !12} ; [ DW_TAG_file_type ] +!2 = !{!"0x11\001\004.2.1 (Based on Apple Inc. build 5658) (LLVM build)\001\00\000\00\000", !12, !4, !4, null, null, null} ; [ DW_TAG_compile_unit ] +!3 = !{!"0x15\00\000\000\000\000\000\000", !12, !1, null, !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!4 = !{null} +!5 = !{!"0x100\00y\003\000", !6, !1, !7} ; [ DW_TAG_auto_variable ] +!6 = !{!"0xb\002\000\000", !12, !0} ; [ DW_TAG_lexical_block ] +!7 = !{!"0x24\00int\000\0032\0032\000\000\005", !12, !1} ; [ DW_TAG_base_type ] +!8 = !{!"0x34\00x\00x\00\001\000\001", !1, !1, !7, i32* @x} ; [ DW_TAG_variable ] +!9 = !{i32 0} +!10 = !MDLocation(line: 3, scope: !6) +!11 = !MDLocation(line: 4, scope: !6) +!12 = !{!"b.c", !"/tmp"} +!13 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/StripSymbols/2010-08-25-crash.ll b/test/Transforms/StripSymbols/2010-08-25-crash.ll index b55ac3c08245..1534647c2a71 100644 --- a/test/Transforms/StripSymbols/2010-08-25-crash.ll +++ b/test/Transforms/StripSymbols/2010-08-25-crash.ll @@ -7,18 +7,18 @@ entry: !llvm.dbg.cu = !{!2} !llvm.module.flags = !{!14} -!0 = metadata !{i32 524334, metadata !10, metadata !1, metadata !"foo", metadata !"foo", metadata !"foo", i32 3, metadata !3, i1 false, i1 true, i32 0, i32 0, null, i1 false, i1 false, i32 ()* @foo, null, null, null, i32 0} ; [ DW_TAG_subprogram ] -!1 = metadata !{i32 524329, metadata !10} ; [ DW_TAG_file_type ] -!2 = metadata !{i32 524305, metadata !10, i32 12, metadata !"clang version 2.8 (trunk 112062)", i1 true, metadata !"", i32 0, metadata !11, metadata !11, metadata !12, metadata !13, null, metadata !"", i32 1} ; [ DW_TAG_compile_unit ] -!3 = metadata !{i32 524309, metadata !10, metadata !1, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !4, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!4 = metadata !{metadata !5} -!5 = metadata !{i32 524324, metadata !10, metadata !1, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] -!6 = metadata !{i32 524340, i32 0, metadata !1, metadata !"i", metadata !"i", metadata !"i", metadata !1, i32 2, metadata !7, i1 true, i1 true, i32 0, null} ; [ DW_TAG_variable ] -!7 = metadata !{i32 524326, metadata !10, metadata !1, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, metadata !5} ; [ DW_TAG_const_type ] -!8 = metadata !{i32 3, i32 13, metadata !9, null} -!9 = metadata !{i32 524299, metadata !10, metadata !0, i32 3, i32 11, i32 0} ; [ DW_TAG_lexical_block ] -!10 = metadata !{metadata !"/tmp/a.c", metadata !"/Volumes/Lalgate/clean/D.CW"} -!11 = metadata !{i32 0} -!12 = metadata !{metadata !0} -!13 = metadata !{metadata !6} -!14 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x2e\00foo\00foo\00foo\003\000\001\000\006\000\000\000", !10, !1, !3, null, i32 ()* @foo, null, null, null} ; [ DW_TAG_subprogram ] +!1 = !{!"0x29", !10} ; [ DW_TAG_file_type ] +!2 = !{!"0x11\0012\00clang version 2.8 (trunk 112062)\001\00\000\00\001", !10, !11, !11, !12, !13, null} ; [ DW_TAG_compile_unit ] +!3 = !{!"0x15\00\000\000\000\000\000\000", !10, !1, null, !4, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!4 = !{!5} +!5 = !{!"0x24\00int\000\0032\0032\000\000\005", !10, !1} ; [ DW_TAG_base_type ] +!6 = !{!"0x34\00i\00i\00i\002\001\001", !1, !1, !7, i32 0, null} ; [ DW_TAG_variable ] +!7 = !{!"0x26\00\000\000\000\000\000", !10, !1, !5} ; [ DW_TAG_const_type ] +!8 = !MDLocation(line: 3, column: 13, scope: !9) +!9 = !{!"0xb\003\0011\000", !10, !0} ; [ DW_TAG_lexical_block ] +!10 = !{!"/tmp/a.c", !"/Volumes/Lalgate/clean/D.CW"} +!11 = !{i32 0} +!12 = !{!0} +!13 = !{!6} +!14 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/StripSymbols/strip-dead-debug-info.ll b/test/Transforms/StripSymbols/strip-dead-debug-info.ll index 8ce7b87c8250..aca7cd608470 100644 --- a/test/Transforms/StripSymbols/strip-dead-debug-info.ll +++ b/test/Transforms/StripSymbols/strip-dead-debug-info.ll @@ -7,7 +7,7 @@ @xyz = global i32 2 ; Function Attrs: nounwind readnone -declare void @llvm.dbg.value(metadata, i64, metadata) #0 +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #0 ; Function Attrs: nounwind readnone ssp define i32 @fn() #1 { @@ -18,7 +18,7 @@ entry: ; Function Attrs: nounwind readonly ssp define i32 @foo(i32 %i) #2 { entry: - tail call void @llvm.dbg.value(metadata !{i32 %i}, i64 0, metadata !15), !dbg !20 + tail call void @llvm.dbg.value(metadata i32 %i, i64 0, metadata !15, metadata !{}), !dbg !20 %.0 = load i32* @xyz, align 4 ret i32 %.0, !dbg !21 } @@ -30,29 +30,29 @@ attributes #2 = { nounwind readonly ssp } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!25} -!0 = metadata !{i32 524305, metadata !1, i32 1, metadata !"4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !23, metadata !24, null, metadata !"", i32 1} ; [ DW_TAG_compile_unit ] [/tmp//g.c] [DW_LANG_C89] -!1 = metadata !{metadata !"g.c", metadata !"/tmp/"} -!2 = metadata !{null} -!3 = metadata !{i32 524334, metadata !1, null, metadata !"bar", metadata !"bar", metadata !"", i32 5, metadata !4, i1 true, i1 true, i32 0, i32 0, null, i1 false, i1 true, null, null, null, null, i32 0} ; [ DW_TAG_subprogram ] [line 5] [local] [def] [scope 0] [bar] -!4 = metadata !{i32 524309, metadata !1, metadata !5, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!5 = metadata !{i32 524329, metadata !1} ; [ DW_TAG_file_type ] [/tmp//g.c] -!6 = metadata !{i32 524334, metadata !1, null, metadata !"fn", metadata !"fn", metadata !"fn", i32 6, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i1 false, i1 true, i32 ()* @fn, null, null, null, i32 0} ; [ DW_TAG_subprogram ] [line 6] [def] [scope 0] [fn] -!7 = metadata !{i32 524309, metadata !1, metadata !5, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!8 = metadata !{metadata !9} -!9 = metadata !{i32 524324, metadata !1, metadata !5, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] -!10 = metadata !{i32 524334, metadata !1, null, metadata !"foo", metadata !"foo", metadata !"foo", i32 7, metadata !11, i1 false, i1 true, i32 0, i32 0, null, i1 false, i1 true, i32 (i32)* @foo, null, null, null, i32 0} ; [ DW_TAG_subprogram ] [line 7] [def] [scope 0] [foo] -!11 = metadata !{i32 524309, metadata !1, metadata !5, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !12, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!12 = metadata !{metadata !9, metadata !9} -!13 = metadata !{i32 524544, metadata !14, metadata !"bb", metadata !5, i32 5, metadata !9} -!14 = metadata !{i32 524299, metadata !1, metadata !3, i32 5, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [/tmp//g.c] -!15 = metadata !{i32 524545, metadata !10, metadata !"i", metadata !5, i32 7, metadata !9} -!16 = metadata !{i32 524340, i32 0, metadata !5, metadata !"abcd", metadata !"abcd", metadata !"", metadata !5, i32 2, metadata !9, i1 true, i1 true, null, null} -!17 = metadata !{i32 524340, i32 0, metadata !5, metadata !"xyz", metadata !"xyz", metadata !"", metadata !5, i32 3, metadata !9, i1 false, i1 true, i32* @xyz, null} -!18 = metadata !{i32 6, i32 0, metadata !19, null} -!19 = metadata !{i32 524299, metadata !1, metadata !6, i32 6, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [/tmp//g.c] -!20 = metadata !{i32 7, i32 0, metadata !10, null} -!21 = metadata !{i32 10, i32 0, metadata !22, null} -!22 = metadata !{i32 524299, metadata !1, metadata !10, i32 7, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [/tmp//g.c] -!23 = metadata !{metadata !3, metadata !6, metadata !10} -!24 = metadata !{metadata !16, metadata !17} -!25 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x11\001\004.2.1 (Based on Apple Inc. build 5658) (LLVM build)\001\00\000\00\001", !1, !2, !2, !23, !24, null} ; [ DW_TAG_compile_unit ] [/tmp//g.c] [DW_LANG_C89] +!1 = !{!"g.c", !"/tmp/"} +!2 = !{null} +!3 = !{!"0x2e\00bar\00bar\00\005\001\001\000\006\000\001\000", !1, null, !4, null, null, null, null, null} ; [ DW_TAG_subprogram ] [line 5] [local] [def] [scope 0] [bar] +!4 = !{!"0x15\00\000\000\000\000\000\000", !1, !5, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [/tmp//g.c] +!6 = !{!"0x2e\00fn\00fn\00fn\006\000\001\000\006\000\001\000", !1, null, !7, null, i32 ()* @fn, null, null, null} ; [ DW_TAG_subprogram ] [line 6] [def] [scope 0] [fn] +!7 = !{!"0x15\00\000\000\000\000\000\000", !1, !5, null, !8, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!8 = !{!9} +!9 = !{!"0x24\00int\000\0032\0032\000\000\005", !1, !5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!10 = !{!"0x2e\00foo\00foo\00foo\007\000\001\000\006\000\001\000", !1, null, !11, null, i32 (i32)* @foo, null, null, null} ; [ DW_TAG_subprogram ] [line 7] [def] [scope 0] [foo] +!11 = !{!"0x15\00\000\000\000\000\000\000", !1, !5, null, !12, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!12 = !{!9, !9} +!13 = !{!"0x100\00bb\005\000", !14, !5, !9} ; [ DW_TAG_auto_variable ] +!14 = !{!"0xb\005\000\000", !1, !3} ; [ DW_TAG_lexical_block ] [/tmp//g.c] +!15 = !{!"0x101\00i\007\000", !10, !5, !9} ; [ DW_TAG_arg_variable ] +!16 = !{!"0x34\00abcd\00abcd\00\002\001\001", !5, !5, !9, null, null} ; [ DW_TAG_variable ] +!17 = !{!"0x34\00xyz\00xyz\00\003\000\001", !5, !5, !9, i32* @xyz, null} ; [ DW_TAG_variable ] +!18 = !MDLocation(line: 6, scope: !19) +!19 = !{!"0xb\006\000\000", !1, !6} ; [ DW_TAG_lexical_block ] [/tmp//g.c] +!20 = !MDLocation(line: 7, scope: !10) +!21 = !MDLocation(line: 10, scope: !22) +!22 = !{!"0xb\007\000\000", !1, !10} ; [ DW_TAG_lexical_block ] [/tmp//g.c] +!23 = !{!3, !6, !10} +!24 = !{!16, !17} +!25 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/StructurizeCFG/one-loop-multiple-backedges.ll b/test/Transforms/StructurizeCFG/one-loop-multiple-backedges.ll new file mode 100644 index 000000000000..8ebd47aefd15 --- /dev/null +++ b/test/Transforms/StructurizeCFG/one-loop-multiple-backedges.ll @@ -0,0 +1,41 @@ +; RUN: opt -S -structurizecfg %s -o - | FileCheck %s + +; CHECK-NOT: br i1 true + +define void @blam(i32 addrspace(1)* nocapture %arg, float %arg1, float %arg2) { +; CHECK: bb: +bb: + br label %bb3 + +; CHECK: bb3: +bb3: ; preds = %bb7, %bb + %tmp = phi i64 [ 0, %bb ], [ %tmp8, %bb7 ] + %tmp4 = fcmp ult float %arg1, 3.500000e+00 +; CHECK: br i1 %tmp4, label %bb7, label %Flow + br i1 %tmp4, label %bb7, label %bb5 + +; CHECK: Flow: +; CHECK: br i1 %2, label %Flow1, label %bb3 + +; CHECK: Flow1: +; CHECK: br i1 %3, label %bb5, label %bb10 + +; CHECK: bb5: +bb5: ; preds = %bb3 + %tmp6 = fcmp olt float 0.000000e+00, %arg2 +; CHECK: br label %bb10 + br i1 %tmp6, label %bb10, label %bb7 + +; CHECK: bb7 +bb7: ; preds = %bb5, %bb3 + %tmp8 = add nuw nsw i64 %tmp, 1 + %tmp9 = icmp slt i64 %tmp8, 5 +; CHECK: br label %Flow + br i1 %tmp9, label %bb3, label %bb10 + +; CHECK: bb10 +bb10: ; preds = %bb7, %bb5 + %tmp11 = phi i32 [ 15, %bb5 ], [ 255, %bb7 ] + store i32 %tmp11, i32 addrspace(1)* %arg, align 4 + ret void +} diff --git a/test/Transforms/TailCallElim/EraseBB.ll b/test/Transforms/TailCallElim/EraseBB.ll new file mode 100644 index 000000000000..c8290d7ea951 --- /dev/null +++ b/test/Transforms/TailCallElim/EraseBB.ll @@ -0,0 +1,26 @@ +; RUN: opt -tailcallelim -S < %s 2>&1 | FileCheck %s + +; CHECK: add nsw i32 +; CHECK-NEXT: br label +; CHECK: add nsw i32 +; CHECK-NEXT: br label +; CHECK-NOT: Uses remain when a value is destroyed +define i32 @test(i32 %n) { +entry: + %cmp = icmp slt i32 %n, 2 + br i1 %cmp, label %if.then, label %if.else + +if.then: ; preds = %entry + %v1 = add nsw i32 %n, -2 + %call1 = tail call i32 @test(i32 %v1) + br label %return + +if.else: ; preds = %entry + %v2 = add nsw i32 %n, 4 + %call2 = tail call i32 @test(i32 %v2) + br label %return + +return: ; preds = %if.end, %if.else + %retval = phi i32 [ %call1, %if.then ], [ %call2, %if.else ] + ret i32 %retval +} diff --git a/test/Transforms/TailCallElim/reorder_load.ll b/test/Transforms/TailCallElim/reorder_load.ll index 53c65dab101b..2e350d662a39 100644 --- a/test/Transforms/TailCallElim/reorder_load.ll +++ b/test/Transforms/TailCallElim/reorder_load.ll @@ -1,6 +1,8 @@ ; RUN: opt < %s -tailcallelim -S | FileCheck %s ; PR4323 +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + ; Several cases where tail call elimination should move the load above the call, ; then eliminate the tail recursion. @@ -12,6 +14,11 @@ ; This load can be moved above the call because the function won't write to it ; and the call has no side effects. define fastcc i32 @raise_load_1(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) nounwind readonly { +; CHECK-LABEL: @raise_load_1( +; CHECK-NOT: call +; CHECK: load i32* +; CHECK-NOT: call +; CHECK: } entry: %tmp2 = icmp sge i32 %start_arg, %a_len_arg ; <i1> [#uses=1] br i1 %tmp2, label %if, label %else @@ -21,7 +28,6 @@ if: ; preds = %entry else: ; preds = %entry %tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1] -; CHECK-NOT: call %tmp8 = call fastcc i32 @raise_load_1(i32* %a_arg, i32 %a_len_arg, i32 %tmp7) ; <i32> [#uses=1] %tmp9 = load i32* %a_arg ; <i32> [#uses=1] %tmp10 = add i32 %tmp9, %tmp8 ; <i32> [#uses=1] @@ -32,6 +38,11 @@ else: ; preds = %entry ; This load can be moved above the call because the function won't write to it ; and the load provably can't trap. define fastcc i32 @raise_load_2(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) readonly { +; CHECK-LABEL: @raise_load_2( +; CHECK-NOT: call +; CHECK: load i32* +; CHECK-NOT: call +; CHECK: } entry: %tmp2 = icmp sge i32 %start_arg, %a_len_arg ; <i1> [#uses=1] br i1 %tmp2, label %if, label %else @@ -48,7 +59,6 @@ unwind: ; preds = %else recurse: ; preds = %else %tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1] -; CHECK-NOT: call %tmp8 = call fastcc i32 @raise_load_2(i32* %a_arg, i32 %a_len_arg, i32 %tmp7) ; <i32> [#uses=1] %tmp9 = load i32* @global ; <i32> [#uses=1] %tmp10 = add i32 %tmp9, %tmp8 ; <i32> [#uses=1] @@ -59,6 +69,11 @@ recurse: ; preds = %else ; This load can be safely moved above the call (even though it's from an ; extern_weak global) because the call has no side effects. define fastcc i32 @raise_load_3(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) nounwind readonly { +; CHECK-LABEL: @raise_load_3( +; CHECK-NOT: call +; CHECK: load i32* +; CHECK-NOT: call +; CHECK: } entry: %tmp2 = icmp sge i32 %start_arg, %a_len_arg ; <i1> [#uses=1] br i1 %tmp2, label %if, label %else @@ -68,7 +83,6 @@ if: ; preds = %entry else: ; preds = %entry %tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1] -; CHECK-NOT: call %tmp8 = call fastcc i32 @raise_load_3(i32* %a_arg, i32 %a_len_arg, i32 %tmp7) ; <i32> [#uses=1] %tmp9 = load i32* @extern_weak_global ; <i32> [#uses=1] %tmp10 = add i32 %tmp9, %tmp8 ; <i32> [#uses=1] @@ -80,6 +94,12 @@ else: ; preds = %entry ; unknown pointer (which normally means it might trap) because the first load ; proves it doesn't trap. define fastcc i32 @raise_load_4(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) readonly { +; CHECK-LABEL: @raise_load_4( +; CHECK-NOT: call +; CHECK: load i32* +; CHECK-NEXT: load i32* +; CHECK-NOT: call +; CHECK: } entry: %tmp2 = icmp sge i32 %start_arg, %a_len_arg ; <i1> [#uses=1] br i1 %tmp2, label %if, label %else @@ -97,7 +117,6 @@ unwind: ; preds = %else recurse: ; preds = %else %tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1] %first = load i32* %a_arg ; <i32> [#uses=1] -; CHECK-NOT: call %tmp8 = call fastcc i32 @raise_load_4(i32* %a_arg, i32 %first, i32 %tmp7) ; <i32> [#uses=1] %second = load i32* %a_arg ; <i32> [#uses=1] %tmp10 = add i32 %second, %tmp8 ; <i32> [#uses=1] diff --git a/test/Transforms/Util/flattencfg.ll b/test/Transforms/Util/flattencfg.ll new file mode 100644 index 000000000000..4fcb77ab0237 --- /dev/null +++ b/test/Transforms/Util/flattencfg.ll @@ -0,0 +1,26 @@ +; RUN: opt -flattencfg -S < %s | FileCheck %s + + +; This test checks whether the pass completes without a crash. +; The code is not transformed in any way +; +; CHECK-LABEL: @test_not_crash +define void @test_not_crash(i32 %in_a) #0 { +entry: + %cmp0 = icmp eq i32 %in_a, -1 + %cmp1 = icmp ne i32 %in_a, 0 + %cond0 = and i1 %cmp0, %cmp1 + br i1 %cond0, label %b0, label %b1 + +b0: ; preds = %entry + %cmp2 = icmp eq i32 %in_a, 0 + %cmp3 = icmp ne i32 %in_a, 1 + %cond1 = or i1 %cmp2, %cmp3 + br i1 %cond1, label %exit, label %b1 + +b1: ; preds = %entry, %b0 + br label %exit + +exit: ; preds = %entry, %b0, %b1 + ret void +} diff --git a/test/Transforms/Util/lowerswitch.ll b/test/Transforms/Util/lowerswitch.ll new file mode 100644 index 000000000000..17c12028705f --- /dev/null +++ b/test/Transforms/Util/lowerswitch.ll @@ -0,0 +1,54 @@ +; RUN: opt -lowerswitch -S < %s | FileCheck %s + +; Test that we don't crash and have a different basic block for each incoming edge. +define void @test0() { +; CHECK-LABEL: @test0 +; CHECK: %merge = phi i64 [ 1, %BB3 ], [ 0, %NewDefault ], [ 0, %NodeBlock5 ], [ 0, %LeafBlock1 ] +BB1: + switch i32 undef, label %BB2 [ + i32 3, label %BB2 + i32 5, label %BB2 + i32 0, label %BB3 + i32 2, label %BB3 + i32 4, label %BB3 + ] + +BB2: + %merge = phi i64 [ 1, %BB3 ], [ 0, %BB1 ], [ 0, %BB1 ], [ 0, %BB1 ] + ret void + +BB3: + br label %BB2 +} + +; Test switch cases that are merged into a single case during lowerswitch +; (take 84 and 85 below) - check that the number of incoming phi values match +; the number of branches. +define void @test1() { +; CHECK-LABEL: @test1 +entry: + br label %bb1 + +bb1: + switch i32 undef, label %bb1 [ + i32 84, label %bb3 + i32 85, label %bb3 + i32 86, label %bb2 + i32 78, label %exit + i32 99, label %bb3 + ] + +bb2: + br label %bb3 + +bb3: +; CHECK-LABEL: bb3 +; CHECK: %tmp = phi i32 [ 1, %NodeBlock ], [ 0, %bb2 ], [ 1, %LeafBlock3 ] + %tmp = phi i32 [ 1, %bb1 ], [ 0, %bb2 ], [ 1, %bb1 ], [ 1, %bb1 ] +; CHECK-NEXT: %tmp2 = phi i32 [ 2, %NodeBlock ], [ 5, %bb2 ], [ 2, %LeafBlock3 ] + %tmp2 = phi i32 [ 2, %bb1 ], [ 2, %bb1 ], [ 5, %bb2 ], [ 2, %bb1 ] + br label %exit + +exit: + ret void +} |