Hans Wennborg | 35905d6 | 2017-02-16 19:04:42 +0000 | [diff] [blame] | 1 | ; RUN: llc < %s -mtriple=i686-linux -show-mc-encoding | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK32 |
Hans Wennborg | a468601 | 2017-02-16 00:04:05 +0000 | [diff] [blame] | 2 | ; RUN: llc < %s -mtriple=x86_64-linux -show-mc-encoding | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK64 |
Hans Wennborg | 35905d6 | 2017-02-16 19:04:42 +0000 | [diff] [blame] | 3 | ; RUN: llc < %s -mtriple=x86_64-win32 -show-mc-encoding | FileCheck %s --check-prefix=CHECK --check-prefix=WIN64 |
Hans Wennborg | a468601 | 2017-02-16 00:04:05 +0000 | [diff] [blame] | 4 | |
| 5 | declare void @foo() |
| 6 | declare void @bar() |
| 7 | |
| 8 | define void @f(i32 %x, i32 %y) optsize { |
| 9 | entry: |
| 10 | %p = icmp eq i32 %x, %y |
| 11 | br i1 %p, label %bb1, label %bb2 |
| 12 | bb1: |
| 13 | tail call void @foo() |
| 14 | ret void |
| 15 | bb2: |
| 16 | tail call void @bar() |
| 17 | ret void |
| 18 | |
| 19 | ; CHECK-LABEL: f: |
| 20 | ; CHECK: cmp |
| 21 | ; CHECK: jne bar |
| 22 | ; Check that the asm doesn't just look good, but uses the correct encoding. |
| 23 | ; CHECK: encoding: [0x75,A] |
| 24 | ; CHECK: jmp foo |
| 25 | } |
| 26 | |
Hans Wennborg | 35905d6 | 2017-02-16 19:04:42 +0000 | [diff] [blame] | 27 | define void @f_non_leaf(i32 %x, i32 %y) optsize { |
| 28 | entry: |
| 29 | ; Force %ebx to be spilled on the stack, turning this into |
| 30 | ; not a "leaf" function for Win64. |
| 31 | tail call void asm sideeffect "", "~{ebx}"() |
| 32 | |
| 33 | %p = icmp eq i32 %x, %y |
| 34 | br i1 %p, label %bb1, label %bb2 |
| 35 | bb1: |
| 36 | tail call void @foo() |
| 37 | ret void |
| 38 | bb2: |
| 39 | tail call void @bar() |
| 40 | ret void |
| 41 | |
| 42 | ; CHECK-LABEL: f_non_leaf: |
| 43 | ; WIN64-NOT: je foo |
| 44 | ; WIN64-NOT: jne bar |
| 45 | ; WIN64: jne |
| 46 | ; WIN64: jmp foo |
| 47 | ; WIN64: jmp bar |
| 48 | } |
Hans Wennborg | a468601 | 2017-02-16 00:04:05 +0000 | [diff] [blame] | 49 | |
| 50 | declare x86_thiscallcc zeroext i1 @baz(i8*, i32) |
| 51 | define x86_thiscallcc zeroext i1 @BlockPlacementTest(i8* %this, i32 %x) optsize { |
| 52 | entry: |
| 53 | %and = and i32 %x, 42 |
| 54 | %tobool = icmp eq i32 %and, 0 |
| 55 | br i1 %tobool, label %land.end, label %land.rhs |
| 56 | |
| 57 | land.rhs: |
| 58 | %and6 = and i32 %x, 44 |
| 59 | %tobool7 = icmp eq i32 %and6, 0 |
| 60 | br i1 %tobool7, label %lor.rhs, label %land.end |
| 61 | |
| 62 | lor.rhs: |
| 63 | %call = tail call x86_thiscallcc zeroext i1 @baz(i8* %this, i32 %x) #2 |
| 64 | br label %land.end |
| 65 | |
| 66 | land.end: |
| 67 | %0 = phi i1 [ false, %entry ], [ true, %land.rhs ], [ %call, %lor.rhs ] |
| 68 | ret i1 %0 |
| 69 | |
| 70 | ; Make sure machine block placement isn't confused by the conditional tail call, |
| 71 | ; but sees that it can fall through to the next block. |
| 72 | ; CHECK-LABEL: BlockPlacementTest |
| 73 | ; CHECK: je baz |
| 74 | ; CHECK-NOT: xor |
| 75 | ; CHECK: ret |
| 76 | } |
| 77 | |
| 78 | |
| 79 | |
| 80 | %"class.std::basic_string" = type { %"struct.std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Alloc_hider" } |
| 81 | %"struct.std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Alloc_hider" = type { i8* } |
| 82 | declare zeroext i1 @_Z20isValidIntegerSuffixN9__gnu_cxx17__normal_iteratorIPKcSsEES3_(i8*, i8*) |
| 83 | |
| 84 | define zeroext i1 @pr31257(%"class.std::basic_string"* nocapture readonly dereferenceable(8) %s) minsize { |
| 85 | ; CHECK-LABEL: pr31257 |
| 86 | entry: |
| 87 | %_M_p.i.i = getelementptr inbounds %"class.std::basic_string", %"class.std::basic_string"* %s, i64 0, i32 0, i32 0 |
| 88 | %0 = load i8*, i8** %_M_p.i.i, align 8 |
| 89 | %arrayidx.i.i.i54 = getelementptr inbounds i8, i8* %0, i64 -24 |
| 90 | %_M_length.i.i55 = bitcast i8* %arrayidx.i.i.i54 to i64* |
| 91 | %1 = load i64, i64* %_M_length.i.i55, align 8 |
| 92 | %add.ptr.i56 = getelementptr inbounds i8, i8* %0, i64 %1 |
| 93 | br label %for.cond |
| 94 | |
| 95 | for.cond: ; preds = %for.inc, %entry |
| 96 | %it.sroa.0.0 = phi i8* [ %0, %entry ], [ %incdec.ptr.i, %for.inc ] |
| 97 | %state.0 = phi i32 [ 0, %entry ], [ %state.1, %for.inc ] |
| 98 | %cmp.i = icmp eq i8* %it.sroa.0.0, %add.ptr.i56 |
| 99 | br i1 %cmp.i, label %5, label %for.body |
| 100 | |
| 101 | for.body: ; preds = %for.cond |
| 102 | switch i32 %state.0, label %for.inc [ |
| 103 | i32 0, label %sw.bb |
| 104 | i32 1, label %sw.bb14 |
| 105 | i32 2, label %sw.bb22 |
| 106 | ] |
| 107 | |
| 108 | sw.bb: ; preds = %for.body |
| 109 | %2 = load i8, i8* %it.sroa.0.0, align 1 |
| 110 | switch i8 %2, label %if.else [ |
| 111 | i8 43, label %for.inc |
| 112 | i8 45, label %for.inc |
| 113 | ] |
| 114 | |
| 115 | if.else: ; preds = %sw.bb |
| 116 | %conv9 = zext i8 %2 to i32 |
| 117 | %isdigittmp45 = add nsw i32 %conv9, -48 |
| 118 | %isdigit46 = icmp ult i32 %isdigittmp45, 10 |
| 119 | br i1 %isdigit46, label %for.inc, label %cleanup.thread.loopexit |
| 120 | |
| 121 | sw.bb14: ; preds = %for.body |
| 122 | %3 = load i8, i8* %it.sroa.0.0, align 1 |
| 123 | %conv16 = zext i8 %3 to i32 |
| 124 | %isdigittmp43 = add nsw i32 %conv16, -48 |
| 125 | %isdigit44 = icmp ult i32 %isdigittmp43, 10 |
| 126 | br i1 %isdigit44, label %for.inc, label %cleanup.thread.loopexit |
| 127 | |
| 128 | sw.bb22: ; preds = %for.body |
| 129 | %4 = load i8, i8* %it.sroa.0.0, align 1 |
| 130 | %conv24 = zext i8 %4 to i32 |
| 131 | %isdigittmp = add nsw i32 %conv24, -48 |
| 132 | %isdigit = icmp ult i32 %isdigittmp, 10 |
| 133 | br i1 %isdigit, label %for.inc, label %if.else28 |
| 134 | |
| 135 | ; Make sure Machine Copy Propagation doesn't delete the mov to %ecx becaue it |
| 136 | ; thinks the conditional tail call clobbers it. |
Hans Wennborg | 35905d6 | 2017-02-16 19:04:42 +0000 | [diff] [blame] | 137 | ; CHECK64-LABEL: .LBB3_11: |
Hans Wennborg | a468601 | 2017-02-16 00:04:05 +0000 | [diff] [blame] | 138 | ; CHECK64: movzbl (%rdi), %ecx |
| 139 | ; CHECK64-NEXT: addl $-48, %ecx |
| 140 | ; CHECK64-NEXT: cmpl $10, %ecx |
| 141 | ; CHECK64-NEXT: movl %r9d, %ecx |
| 142 | ; CHECK64-NEXT: jae _Z20isValidIntegerSuffixN9__gnu_cxx17__normal_iteratorIPKcSsEE |
| 143 | |
| 144 | if.else28: ; preds = %sw.bb22 |
| 145 | %call34 = tail call zeroext i1 @_Z20isValidIntegerSuffixN9__gnu_cxx17__normal_iteratorIPKcSsEES3_(i8* nonnull %it.sroa.0.0, i8* %add.ptr.i56) |
| 146 | br label %cleanup.thread |
| 147 | |
| 148 | for.inc: ; preds = %sw.bb, %sw.bb, %sw.bb22, %sw.bb14, %if.else, %for.body |
| 149 | %state.1 = phi i32 [ %state.0, %for.body ], [ 1, %sw.bb ], [ 2, %if.else ], [ 2, %sw.bb14 ], [ 2, %sw.bb22 ], [ 1, %sw.bb ] |
| 150 | %incdec.ptr.i = getelementptr inbounds i8, i8* %it.sroa.0.0, i64 1 |
| 151 | br label %for.cond |
| 152 | |
| 153 | ; <label>:5: ; preds = %for.cond |
| 154 | %cmp37 = icmp eq i32 %state.0, 2 |
| 155 | br label %cleanup.thread |
| 156 | |
| 157 | cleanup.thread.loopexit: ; preds = %if.else, %sw.bb14 |
| 158 | br label %cleanup.thread |
| 159 | |
| 160 | cleanup.thread: ; preds = %cleanup.thread.loopexit, %if.else28, %5 |
| 161 | %6 = phi i1 [ %cmp37, %5 ], [ %call34, %if.else28 ], [ false, %cleanup.thread.loopexit ] |
| 162 | ret i1 %6 |
| 163 | } |