| OLD | NEW |
| 1 ; This tests the NaCl intrinsics not related to atomic operations. | 1 ; This tests the NaCl intrinsics not related to atomic operations. |
| 2 | 2 |
| 3 ; RUN: %p2i -i %s --args -O2 --verbose none -sandbox \ | 3 ; RUN: %p2i -i %s --assemble --disassemble --args -O2 --verbose none -sandbox \ |
| 4 ; RUN: | llvm-mc -triple=i686-none-nacl -filetype=obj \ | 4 ; RUN: | FileCheck %s |
| 5 ; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s | 5 ; RUN: %p2i -i %s --assemble --disassemble --args -Om1 --verbose none -sandbox \ |
| 6 ; RUN: %p2i -i %s --args -Om1 --verbose none -sandbox \ | 6 ; RUN: | FileCheck %s |
| 7 ; RUN: | llvm-mc -triple=i686-none-nacl -filetype=obj \ | |
| 8 ; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s | |
| 9 | 7 |
| 10 ; Do another run w/ O2 and a different check-prefix (otherwise O2 and Om1 | 8 ; Do another run w/ O2 and a different check-prefix (otherwise O2 and Om1 |
| 11 ; share the same "CHECK" prefix). This separate run helps check that | 9 ; share the same "CHECK" prefix). This separate run helps check that |
| 12 ; some code is optimized out. | 10 ; some code is optimized out. |
| 13 ; RUN: %p2i -i %s --args -O2 --verbose none -sandbox \ | 11 ; RUN: %p2i -i %s --assemble --disassemble --args -O2 --verbose none -sandbox \ |
| 14 ; RUN: | llvm-mc -triple=i686-none-nacl -filetype=obj \ | |
| 15 ; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - \ | |
| 16 ; RUN: | FileCheck --check-prefix=CHECKO2REM %s | 12 ; RUN: | FileCheck --check-prefix=CHECKO2REM %s |
| 17 | 13 |
| 18 ; Do O2 runs without -sandbox to make sure llvm.nacl.read.tp gets | 14 ; Do O2 runs without -sandbox to make sure llvm.nacl.read.tp gets |
| 19 ; lowered to __nacl_read_tp instead of gs:[0x0]. | 15 ; lowered to __nacl_read_tp instead of gs:0x0. |
| 20 ; We also know that because it's O2, it'll have the O2REM optimizations. | 16 ; We also know that because it's O2, it'll have the O2REM optimizations. |
| 21 ; RUN: %p2i -i %s --args -O2 --verbose none \ | 17 ; RUN: %p2i -i %s --assemble --disassemble --args -O2 --verbose none \ |
| 22 ; RUN: | llvm-mc -triple=i686-none-nacl -filetype=obj \ | |
| 23 ; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - \ | |
| 24 ; RUN: | FileCheck --check-prefix=CHECKO2UNSANDBOXEDREM %s | 18 ; RUN: | FileCheck --check-prefix=CHECKO2UNSANDBOXEDREM %s |
| 25 | 19 |
| 26 declare i8* @llvm.nacl.read.tp() | 20 declare i8* @llvm.nacl.read.tp() |
| 27 declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) | 21 declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) |
| 28 declare void @llvm.memmove.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) | 22 declare void @llvm.memmove.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) |
| 29 declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i32, i1) | 23 declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i32, i1) |
| 30 declare void @llvm.nacl.longjmp(i8*, i32) | 24 declare void @llvm.nacl.longjmp(i8*, i32) |
| 31 declare i32 @llvm.nacl.setjmp(i8*) | 25 declare i32 @llvm.nacl.setjmp(i8*) |
| 32 declare float @llvm.sqrt.f32(float) | 26 declare float @llvm.sqrt.f32(float) |
| 33 declare double @llvm.sqrt.f64(double) | 27 declare double @llvm.sqrt.f64(double) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 44 declare i8* @llvm.stacksave() | 38 declare i8* @llvm.stacksave() |
| 45 declare void @llvm.stackrestore(i8*) | 39 declare void @llvm.stackrestore(i8*) |
| 46 | 40 |
| 47 define i32 @test_nacl_read_tp() { | 41 define i32 @test_nacl_read_tp() { |
| 48 entry: | 42 entry: |
| 49 %ptr = call i8* @llvm.nacl.read.tp() | 43 %ptr = call i8* @llvm.nacl.read.tp() |
| 50 %__1 = ptrtoint i8* %ptr to i32 | 44 %__1 = ptrtoint i8* %ptr to i32 |
| 51 ret i32 %__1 | 45 ret i32 %__1 |
| 52 } | 46 } |
| 53 ; CHECK-LABEL: test_nacl_read_tp | 47 ; CHECK-LABEL: test_nacl_read_tp |
| 54 ; CHECK: mov e{{.*}}, dword ptr gs:[0] | 48 ; CHECK: mov e{{.*}},DWORD PTR gs:0x0 |
| 55 ; CHECKO2REM-LABEL: test_nacl_read_tp | 49 ; CHECKO2REM-LABEL: test_nacl_read_tp |
| 56 ; CHECKO2REM: mov e{{.*}}, dword ptr gs:[0] | 50 ; CHECKO2REM: mov e{{.*}},DWORD PTR gs:0x0 |
| 57 ; CHECKO2UNSANDBOXEDREM-LABEL: test_nacl_read_tp | 51 ; CHECKO2UNSANDBOXEDREM-LABEL: test_nacl_read_tp |
| 58 ; CHECKO2UNSANDBOXEDREM: call __nacl_read_tp | 52 ; CHECKO2UNSANDBOXEDREM: call {{.*}} R_{{.*}} __nacl_read_tp |
| 59 | 53 |
| 60 define i32 @test_nacl_read_tp_more_addressing() { | 54 define i32 @test_nacl_read_tp_more_addressing() { |
| 61 entry: | 55 entry: |
| 62 %ptr = call i8* @llvm.nacl.read.tp() | 56 %ptr = call i8* @llvm.nacl.read.tp() |
| 63 %__1 = ptrtoint i8* %ptr to i32 | 57 %__1 = ptrtoint i8* %ptr to i32 |
| 64 %x = add i32 %__1, %__1 | 58 %x = add i32 %__1, %__1 |
| 65 %__3 = inttoptr i32 %x to i32* | 59 %__3 = inttoptr i32 %x to i32* |
| 66 %v = load i32* %__3, align 1 | 60 %v = load i32* %__3, align 1 |
| 67 %v_add = add i32 %v, 1 | 61 %v_add = add i32 %v, 1 |
| 68 | 62 |
| 69 %ptr2 = call i8* @llvm.nacl.read.tp() | 63 %ptr2 = call i8* @llvm.nacl.read.tp() |
| 70 %__6 = ptrtoint i8* %ptr2 to i32 | 64 %__6 = ptrtoint i8* %ptr2 to i32 |
| 71 %y = add i32 %__6, 4 | 65 %y = add i32 %__6, 4 |
| 72 %__8 = inttoptr i32 %y to i32* | 66 %__8 = inttoptr i32 %y to i32* |
| 73 %v_add2 = add i32 %v, 4 | 67 %v_add2 = add i32 %v, 4 |
| 74 store i32 %v_add2, i32* %__8, align 1 | 68 store i32 %v_add2, i32* %__8, align 1 |
| 75 ret i32 %v | 69 ret i32 %v |
| 76 } | 70 } |
| 77 ; CHECK-LABEL: test_nacl_read_tp_more_addressing | 71 ; CHECK-LABEL: test_nacl_read_tp_more_addressing |
| 78 ; CHECK: mov e{{.*}}, dword ptr gs:[0] | 72 ; CHECK: mov e{{.*}},DWORD PTR gs:0x0 |
| 79 ; CHECK: mov e{{.*}}, dword ptr gs:[0] | 73 ; CHECK: mov e{{.*}},DWORD PTR gs:0x0 |
| 80 ; CHECKO2REM-LABEL: test_nacl_read_tp_more_addressing | 74 ; CHECKO2REM-LABEL: test_nacl_read_tp_more_addressing |
| 81 ; CHECKO2REM: mov e{{.*}}, dword ptr gs:[0] | 75 ; CHECKO2REM: mov e{{.*}},DWORD PTR gs:0x0 |
| 82 ; CHECKO2REM: mov e{{.*}}, dword ptr gs:[0] | 76 ; CHECKO2REM: mov e{{.*}},DWORD PTR gs:0x0 |
| 83 ; CHECKO2UNSANDBOXEDREM-LABEL: test_nacl_read_tp_more_addressing | 77 ; CHECKO2UNSANDBOXEDREM-LABEL: test_nacl_read_tp_more_addressing |
| 84 ; CHECKO2UNSANDBOXEDREM: call __nacl_read_tp | 78 ; CHECKO2UNSANDBOXEDREM: call {{.*}} R_{{.*}} __nacl_read_tp |
| 85 ; CHECKO2UNSANDBOXEDREM: call __nacl_read_tp | 79 ; CHECKO2UNSANDBOXEDREM: call {{.*}} R_{{.*}} __nacl_read_tp |
| 86 | 80 |
| 87 define i32 @test_nacl_read_tp_dead(i32 %a) { | 81 define i32 @test_nacl_read_tp_dead(i32 %a) { |
| 88 entry: | 82 entry: |
| 89 %ptr = call i8* @llvm.nacl.read.tp() | 83 %ptr = call i8* @llvm.nacl.read.tp() |
| 90 ; Not actually using the result of nacl read tp call. | 84 ; Not actually using the result of nacl read tp call. |
| 91 ; In O2 mode this should be DCE'ed. | 85 ; In O2 mode this should be DCE'ed. |
| 92 ret i32 %a | 86 ret i32 %a |
| 93 } | 87 } |
| 94 ; Consider nacl.read.tp side-effect free, so it can be eliminated. | 88 ; Consider nacl.read.tp side-effect free, so it can be eliminated. |
| 95 ; CHECKO2REM-LABEL: test_nacl_read_tp_dead | 89 ; CHECKO2REM-LABEL: test_nacl_read_tp_dead |
| 96 ; CHECKO2REM-NOT: mov e{{.*}}, dword ptr gs:[0] | 90 ; CHECKO2REM-NOT: mov e{{.*}}, DWORD PTR gs:0x0 |
| 97 ; CHECKO2UNSANDBOXEDREM-LABEL: test_nacl_read_tp_dead | 91 ; CHECKO2UNSANDBOXEDREM-LABEL: test_nacl_read_tp_dead |
| 98 ; CHECKO2UNSANDBOXEDREM-NOT: call __nacl_read_tp | 92 ; CHECKO2UNSANDBOXEDREM-NOT: call {{.*}} R_{{.*}} __nacl_read_tp |
| 99 | 93 |
| 100 define void @test_memcpy(i32 %iptr_dst, i32 %iptr_src, i32 %len) { | 94 define void @test_memcpy(i32 %iptr_dst, i32 %iptr_src, i32 %len) { |
| 101 entry: | 95 entry: |
| 102 %dst = inttoptr i32 %iptr_dst to i8* | 96 %dst = inttoptr i32 %iptr_dst to i8* |
| 103 %src = inttoptr i32 %iptr_src to i8* | 97 %src = inttoptr i32 %iptr_src to i8* |
| 104 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, | 98 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, |
| 105 i32 %len, i32 1, i1 false) | 99 i32 %len, i32 1, i1 false) |
| 106 ret void | 100 ret void |
| 107 } | 101 } |
| 108 ; CHECK-LABEL: test_memcpy | 102 ; CHECK-LABEL: test_memcpy |
| 109 ; CHECK: call memcpy | 103 ; CHECK: call {{.*}} R_{{.*}} memcpy |
| 110 ; CHECKO2REM-LABEL: test_memcpy | 104 ; CHECKO2REM-LABEL: test_memcpy |
| 111 ; CHECKO2UNSANDBOXEDREM-LABEL: test_memcpy | 105 ; CHECKO2UNSANDBOXEDREM-LABEL: test_memcpy |
| 112 | 106 |
| 113 ; TODO(jvoung) -- if we want to be clever, we can do this and the memmove, | 107 ; TODO(jvoung) -- if we want to be clever, we can do this and the memmove, |
| 114 ; memset without a function call. | 108 ; memset without a function call. |
| 115 define void @test_memcpy_const_len_align(i32 %iptr_dst, i32 %iptr_src) { | 109 define void @test_memcpy_const_len_align(i32 %iptr_dst, i32 %iptr_src) { |
| 116 entry: | 110 entry: |
| 117 %dst = inttoptr i32 %iptr_dst to i8* | 111 %dst = inttoptr i32 %iptr_dst to i8* |
| 118 %src = inttoptr i32 %iptr_src to i8* | 112 %src = inttoptr i32 %iptr_src to i8* |
| 119 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, | 113 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, |
| 120 i32 8, i32 1, i1 false) | 114 i32 8, i32 1, i1 false) |
| 121 ret void | 115 ret void |
| 122 } | 116 } |
| 123 ; CHECK-LABEL: test_memcpy_const_len_align | 117 ; CHECK-LABEL: test_memcpy_const_len_align |
| 124 ; CHECK: call memcpy | 118 ; CHECK: call {{.*}} R_{{.*}} memcpy |
| 125 | 119 |
| 126 define void @test_memmove(i32 %iptr_dst, i32 %iptr_src, i32 %len) { | 120 define void @test_memmove(i32 %iptr_dst, i32 %iptr_src, i32 %len) { |
| 127 entry: | 121 entry: |
| 128 %dst = inttoptr i32 %iptr_dst to i8* | 122 %dst = inttoptr i32 %iptr_dst to i8* |
| 129 %src = inttoptr i32 %iptr_src to i8* | 123 %src = inttoptr i32 %iptr_src to i8* |
| 130 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dst, i8* %src, | 124 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dst, i8* %src, |
| 131 i32 %len, i32 1, i1 false) | 125 i32 %len, i32 1, i1 false) |
| 132 ret void | 126 ret void |
| 133 } | 127 } |
| 134 ; CHECK-LABEL: test_memmove | 128 ; CHECK-LABEL: test_memmove |
| 135 ; CHECK: call memmove | 129 ; CHECK: call {{.*}} R_{{.*}} memmove |
| 136 | 130 |
| 137 define void @test_memmove_const_len_align(i32 %iptr_dst, i32 %iptr_src) { | 131 define void @test_memmove_const_len_align(i32 %iptr_dst, i32 %iptr_src) { |
| 138 entry: | 132 entry: |
| 139 %dst = inttoptr i32 %iptr_dst to i8* | 133 %dst = inttoptr i32 %iptr_dst to i8* |
| 140 %src = inttoptr i32 %iptr_src to i8* | 134 %src = inttoptr i32 %iptr_src to i8* |
| 141 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dst, i8* %src, | 135 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dst, i8* %src, |
| 142 i32 8, i32 1, i1 false) | 136 i32 8, i32 1, i1 false) |
| 143 ret void | 137 ret void |
| 144 } | 138 } |
| 145 ; CHECK-LABEL: test_memmove_const_len_align | 139 ; CHECK-LABEL: test_memmove_const_len_align |
| 146 ; CHECK: call memmove | 140 ; CHECK: call {{.*}} R_{{.*}} memmove |
| 147 | 141 |
| 148 define void @test_memset(i32 %iptr_dst, i32 %wide_val, i32 %len) { | 142 define void @test_memset(i32 %iptr_dst, i32 %wide_val, i32 %len) { |
| 149 entry: | 143 entry: |
| 150 %val = trunc i32 %wide_val to i8 | 144 %val = trunc i32 %wide_val to i8 |
| 151 %dst = inttoptr i32 %iptr_dst to i8* | 145 %dst = inttoptr i32 %iptr_dst to i8* |
| 152 call void @llvm.memset.p0i8.i32(i8* %dst, i8 %val, | 146 call void @llvm.memset.p0i8.i32(i8* %dst, i8 %val, |
| 153 i32 %len, i32 1, i1 false) | 147 i32 %len, i32 1, i1 false) |
| 154 ret void | 148 ret void |
| 155 } | 149 } |
| 156 ; CHECK-LABEL: test_memset | 150 ; CHECK-LABEL: test_memset |
| 157 ; CHECK: movzx | 151 ; CHECK: movzx |
| 158 ; CHECK: call memset | 152 ; CHECK: call {{.*}} R_{{.*}} memset |
| 159 | 153 |
| 160 define void @test_memset_const_len_align(i32 %iptr_dst, i32 %wide_val) { | 154 define void @test_memset_const_len_align(i32 %iptr_dst, i32 %wide_val) { |
| 161 entry: | 155 entry: |
| 162 %val = trunc i32 %wide_val to i8 | 156 %val = trunc i32 %wide_val to i8 |
| 163 %dst = inttoptr i32 %iptr_dst to i8* | 157 %dst = inttoptr i32 %iptr_dst to i8* |
| 164 call void @llvm.memset.p0i8.i32(i8* %dst, i8 %val, | 158 call void @llvm.memset.p0i8.i32(i8* %dst, i8 %val, |
| 165 i32 8, i32 1, i1 false) | 159 i32 8, i32 1, i1 false) |
| 166 ret void | 160 ret void |
| 167 } | 161 } |
| 168 ; CHECK-LABEL: test_memset_const_len_align | 162 ; CHECK-LABEL: test_memset_const_len_align |
| 169 ; CHECK: movzx | 163 ; CHECK: movzx |
| 170 ; CHECK: call memset | 164 ; CHECK: call {{.*}} R_{{.*}} memset |
| 171 | 165 |
| 172 define void @test_memset_const_val(i32 %iptr_dst, i32 %len) { | 166 define void @test_memset_const_val(i32 %iptr_dst, i32 %len) { |
| 173 entry: | 167 entry: |
| 174 %dst = inttoptr i32 %iptr_dst to i8* | 168 %dst = inttoptr i32 %iptr_dst to i8* |
| 175 call void @llvm.memset.p0i8.i32(i8* %dst, i8 0, i32 %len, i32 1, i1 false) | 169 call void @llvm.memset.p0i8.i32(i8* %dst, i8 0, i32 %len, i32 1, i1 false) |
| 176 ret void | 170 ret void |
| 177 } | 171 } |
| 178 ; CHECK-LABEL: test_memset_const_val | 172 ; CHECK-LABEL: test_memset_const_val |
| 179 ; Make sure the argument is legalized (can't movzx reg, 0). | 173 ; Make sure the argument is legalized (can't movzx reg, 0). |
| 180 ; CHECK: movzx {{.*}}, {{[^0]}} | 174 ; CHECK: movzx {{.*}},{{[^0]}} |
| 181 ; CHECK: call memset | 175 ; CHECK: call {{.*}} R_{{.*}} memset |
| 182 | 176 |
| 183 | 177 |
| 184 define i32 @test_setjmplongjmp(i32 %iptr_env) { | 178 define i32 @test_setjmplongjmp(i32 %iptr_env) { |
| 185 entry: | 179 entry: |
| 186 %env = inttoptr i32 %iptr_env to i8* | 180 %env = inttoptr i32 %iptr_env to i8* |
| 187 %i = call i32 @llvm.nacl.setjmp(i8* %env) | 181 %i = call i32 @llvm.nacl.setjmp(i8* %env) |
| 188 %r1 = icmp eq i32 %i, 0 | 182 %r1 = icmp eq i32 %i, 0 |
| 189 br i1 %r1, label %Zero, label %NonZero | 183 br i1 %r1, label %Zero, label %NonZero |
| 190 Zero: | 184 Zero: |
| 191 ; Redundant inttoptr, to make --pnacl cast-eliding/re-insertion happy. | 185 ; Redundant inttoptr, to make --pnacl cast-eliding/re-insertion happy. |
| 192 %env2 = inttoptr i32 %iptr_env to i8* | 186 %env2 = inttoptr i32 %iptr_env to i8* |
| 193 call void @llvm.nacl.longjmp(i8* %env2, i32 1) | 187 call void @llvm.nacl.longjmp(i8* %env2, i32 1) |
| 194 ret i32 0 | 188 ret i32 0 |
| 195 NonZero: | 189 NonZero: |
| 196 ret i32 1 | 190 ret i32 1 |
| 197 } | 191 } |
| 198 ; CHECK-LABEL: test_setjmplongjmp | 192 ; CHECK-LABEL: test_setjmplongjmp |
| 199 ; CHECK: call setjmp | 193 ; CHECK: call {{.*}} R_{{.*}} setjmp |
| 200 ; CHECK: call longjmp | 194 ; CHECK: call {{.*}} R_{{.*}} longjmp |
| 201 ; CHECKO2REM-LABEL: test_setjmplongjmp | 195 ; CHECKO2REM-LABEL: test_setjmplongjmp |
| 202 ; CHECKO2REM: call setjmp | 196 ; CHECKO2REM: call {{.*}} R_{{.*}} setjmp |
| 203 ; CHECKO2REM: call longjmp | 197 ; CHECKO2REM: call {{.*}} R_{{.*}} longjmp |
| 204 | 198 |
| 205 define i32 @test_setjmp_unused(i32 %iptr_env, i32 %i_other) { | 199 define i32 @test_setjmp_unused(i32 %iptr_env, i32 %i_other) { |
| 206 entry: | 200 entry: |
| 207 %env = inttoptr i32 %iptr_env to i8* | 201 %env = inttoptr i32 %iptr_env to i8* |
| 208 %i = call i32 @llvm.nacl.setjmp(i8* %env) | 202 %i = call i32 @llvm.nacl.setjmp(i8* %env) |
| 209 ret i32 %i_other | 203 ret i32 %i_other |
| 210 } | 204 } |
| 211 ; Don't consider setjmp side-effect free, so it's not eliminated if | 205 ; Don't consider setjmp side-effect free, so it's not eliminated if |
| 212 ; result unused. | 206 ; result unused. |
| 213 ; CHECKO2REM-LABEL: test_setjmp_unused | 207 ; CHECKO2REM-LABEL: test_setjmp_unused |
| 214 ; CHECKO2REM: call setjmp | 208 ; CHECKO2REM: call {{.*}} R_{{.*}} setjmp |
| 215 | 209 |
| 216 define float @test_sqrt_float(float %x, i32 %iptr) { | 210 define float @test_sqrt_float(float %x, i32 %iptr) { |
| 217 entry: | 211 entry: |
| 218 %r = call float @llvm.sqrt.f32(float %x) | 212 %r = call float @llvm.sqrt.f32(float %x) |
| 219 %r2 = call float @llvm.sqrt.f32(float %r) | 213 %r2 = call float @llvm.sqrt.f32(float %r) |
| 220 %r3 = call float @llvm.sqrt.f32(float -0.0) | 214 %r3 = call float @llvm.sqrt.f32(float -0.0) |
| 221 %r4 = fadd float %r2, %r3 | 215 %r4 = fadd float %r2, %r3 |
| 222 ret float %r4 | 216 ret float %r4 |
| 223 } | 217 } |
| 224 ; CHECK-LABEL: test_sqrt_float | 218 ; CHECK-LABEL: test_sqrt_float |
| 225 ; CHECK: sqrtss xmm{{.*}} | 219 ; CHECK: sqrtss xmm{{.*}} |
| 226 ; CHECK: sqrtss xmm{{.*}} | 220 ; CHECK: sqrtss xmm{{.*}} |
| 227 ; CHECK: sqrtss xmm{{.*}}, dword ptr | 221 ; CHECK: sqrtss xmm{{.*}},DWORD PTR |
| 228 | 222 |
| 229 define float @test_sqrt_float_mergeable_load(float %x, i32 %iptr) { | 223 define float @test_sqrt_float_mergeable_load(float %x, i32 %iptr) { |
| 230 entry: | 224 entry: |
| 231 %__2 = inttoptr i32 %iptr to float* | 225 %__2 = inttoptr i32 %iptr to float* |
| 232 %y = load float* %__2, align 4 | 226 %y = load float* %__2, align 4 |
| 233 %r5 = call float @llvm.sqrt.f32(float %y) | 227 %r5 = call float @llvm.sqrt.f32(float %y) |
| 234 %r6 = fadd float %x, %r5 | 228 %r6 = fadd float %x, %r5 |
| 235 ret float %r6 | 229 ret float %r6 |
| 236 } | 230 } |
| 237 ; CHECK-LABEL: test_sqrt_float_mergeable_load | 231 ; CHECK-LABEL: test_sqrt_float_mergeable_load |
| 238 ; We could fold the load and the sqrt into one operation, but the | 232 ; We could fold the load and the sqrt into one operation, but the |
| 239 ; current folding only handles load + arithmetic op. The sqrt inst | 233 ; current folding only handles load + arithmetic op. The sqrt inst |
| 240 ; is considered an intrinsic call and not an arithmetic op. | 234 ; is considered an intrinsic call and not an arithmetic op. |
| 241 ; CHECK: sqrtss xmm{{.*}} | 235 ; CHECK: sqrtss xmm{{.*}} |
| 242 | 236 |
| 243 define double @test_sqrt_double(double %x, i32 %iptr) { | 237 define double @test_sqrt_double(double %x, i32 %iptr) { |
| 244 entry: | 238 entry: |
| 245 %r = call double @llvm.sqrt.f64(double %x) | 239 %r = call double @llvm.sqrt.f64(double %x) |
| 246 %r2 = call double @llvm.sqrt.f64(double %r) | 240 %r2 = call double @llvm.sqrt.f64(double %r) |
| 247 %r3 = call double @llvm.sqrt.f64(double -0.0) | 241 %r3 = call double @llvm.sqrt.f64(double -0.0) |
| 248 %r4 = fadd double %r2, %r3 | 242 %r4 = fadd double %r2, %r3 |
| 249 ret double %r4 | 243 ret double %r4 |
| 250 } | 244 } |
| 251 ; CHECK-LABEL: test_sqrt_double | 245 ; CHECK-LABEL: test_sqrt_double |
| 252 ; CHECK: sqrtsd xmm{{.*}} | 246 ; CHECK: sqrtsd xmm{{.*}} |
| 253 ; CHECK: sqrtsd xmm{{.*}} | 247 ; CHECK: sqrtsd xmm{{.*}} |
| 254 ; CHECK: sqrtsd xmm{{.*}}, qword ptr | 248 ; CHECK: sqrtsd xmm{{.*}},QWORD PTR |
| 255 | 249 |
| 256 define double @test_sqrt_double_mergeable_load(double %x, i32 %iptr) { | 250 define double @test_sqrt_double_mergeable_load(double %x, i32 %iptr) { |
| 257 entry: | 251 entry: |
| 258 %__2 = inttoptr i32 %iptr to double* | 252 %__2 = inttoptr i32 %iptr to double* |
| 259 %y = load double* %__2, align 8 | 253 %y = load double* %__2, align 8 |
| 260 %r5 = call double @llvm.sqrt.f64(double %y) | 254 %r5 = call double @llvm.sqrt.f64(double %y) |
| 261 %r6 = fadd double %x, %r5 | 255 %r6 = fadd double %x, %r5 |
| 262 ret double %r6 | 256 ret double %r6 |
| 263 } | 257 } |
| 264 ; CHECK-LABEL: test_sqrt_double_mergeable_load | 258 ; CHECK-LABEL: test_sqrt_double_mergeable_load |
| (...skipping 25 matching lines...) Expand all Loading... |
| 290 define i32 @test_bswap_16(i32 %x) { | 284 define i32 @test_bswap_16(i32 %x) { |
| 291 entry: | 285 entry: |
| 292 %x_trunc = trunc i32 %x to i16 | 286 %x_trunc = trunc i32 %x to i16 |
| 293 %r = call i16 @llvm.bswap.i16(i16 %x_trunc) | 287 %r = call i16 @llvm.bswap.i16(i16 %x_trunc) |
| 294 %r_zext = zext i16 %r to i32 | 288 %r_zext = zext i16 %r to i32 |
| 295 ret i32 %r_zext | 289 ret i32 %r_zext |
| 296 } | 290 } |
| 297 ; CHECK-LABEL: test_bswap_16 | 291 ; CHECK-LABEL: test_bswap_16 |
| 298 ; Make sure this is the right operand size so that the most significant bit | 292 ; Make sure this is the right operand size so that the most significant bit |
| 299 ; to least significant bit rotation happens at the right boundary. | 293 ; to least significant bit rotation happens at the right boundary. |
| 300 ; CHECK: rol {{[abcd]x|si|di|bp|word ptr}}, 8 | 294 ; CHECK: rol {{[abcd]x|si|di|bp|word ptr}},0x8 |
| 301 | 295 |
| 302 define i32 @test_bswap_32(i32 %x) { | 296 define i32 @test_bswap_32(i32 %x) { |
| 303 entry: | 297 entry: |
| 304 %r = call i32 @llvm.bswap.i32(i32 %x) | 298 %r = call i32 @llvm.bswap.i32(i32 %x) |
| 305 ret i32 %r | 299 ret i32 %r |
| 306 } | 300 } |
| 307 ; CHECK-LABEL: test_bswap_32 | 301 ; CHECK-LABEL: test_bswap_32 |
| 308 ; CHECK: bswap e{{.*}} | 302 ; CHECK: bswap e{{.*}} |
| 309 | 303 |
| 310 define i64 @test_bswap_64(i64 %x) { | 304 define i64 @test_bswap_64(i64 %x) { |
| 311 entry: | 305 entry: |
| 312 %r = call i64 @llvm.bswap.i64(i64 %x) | 306 %r = call i64 @llvm.bswap.i64(i64 %x) |
| 313 ret i64 %r | 307 ret i64 %r |
| 314 } | 308 } |
| 315 ; CHECK-LABEL: test_bswap_64 | 309 ; CHECK-LABEL: test_bswap_64 |
| 316 ; CHECK: bswap e{{.*}} | 310 ; CHECK: bswap e{{.*}} |
| 317 ; CHECK: bswap e{{.*}} | 311 ; CHECK: bswap e{{.*}} |
| 318 | 312 |
| 319 define i32 @test_ctlz_32(i32 %x) { | 313 define i32 @test_ctlz_32(i32 %x) { |
| 320 entry: | 314 entry: |
| 321 %r = call i32 @llvm.ctlz.i32(i32 %x, i1 false) | 315 %r = call i32 @llvm.ctlz.i32(i32 %x, i1 false) |
| 322 ret i32 %r | 316 ret i32 %r |
| 323 } | 317 } |
| 324 ; CHECK-LABEL: test_ctlz_32 | 318 ; CHECK-LABEL: test_ctlz_32 |
| 325 ; TODO(jvoung): If we detect that LZCNT is supported, then use that | 319 ; TODO(jvoung): If we detect that LZCNT is supported, then use that |
| 326 ; and avoid the need to do the cmovne and xor stuff to guarantee that | 320 ; and avoid the need to do the cmovne and xor stuff to guarantee that |
| 327 ; the result is well-defined w/ input == 0. | 321 ; the result is well-defined w/ input == 0. |
| 328 ; CHECK: bsr [[REG_TMP:e.*]], {{.*}} | 322 ; CHECK: bsr [[REG_TMP:e.*]],{{.*}} |
| 329 ; CHECK: mov [[REG_RES:e.*]], 63 | 323 ; CHECK: mov [[REG_RES:e.*]],0x3f |
| 330 ; CHECK: cmovne [[REG_RES]], [[REG_TMP]] | 324 ; CHECK: cmovne [[REG_RES]],[[REG_TMP]] |
| 331 ; CHECK: xor [[REG_RES]], 31 | 325 ; CHECK: xor [[REG_RES]],0x1f |
| 332 | 326 |
| 333 define i32 @test_ctlz_32_const() { | 327 define i32 @test_ctlz_32_const() { |
| 334 entry: | 328 entry: |
| 335 %r = call i32 @llvm.ctlz.i32(i32 123456, i1 false) | 329 %r = call i32 @llvm.ctlz.i32(i32 123456, i1 false) |
| 336 ret i32 %r | 330 ret i32 %r |
| 337 } | 331 } |
| 338 ; Could potentially constant fold this, but the front-end should have done that. | 332 ; Could potentially constant fold this, but the front-end should have done that. |
| 339 ; The dest operand must be a register and the source operand must be a register | 333 ; The dest operand must be a register and the source operand must be a register |
| 340 ; or memory. | 334 ; or memory. |
| 341 ; CHECK-LABEL: test_ctlz_32_const | 335 ; CHECK-LABEL: test_ctlz_32_const |
| 342 ; CHECK: bsr e{{.*}}, {{.*}}e{{.*}} | 336 ; CHECK: bsr e{{.*}},{{.*}}e{{.*}} |
| 343 | 337 |
| 344 define i32 @test_ctlz_32_ignored(i32 %x) { | 338 define i32 @test_ctlz_32_ignored(i32 %x) { |
| 345 entry: | 339 entry: |
| 346 %ignored = call i32 @llvm.ctlz.i32(i32 %x, i1 false) | 340 %ignored = call i32 @llvm.ctlz.i32(i32 %x, i1 false) |
| 347 ret i32 1 | 341 ret i32 1 |
| 348 } | 342 } |
| 349 ; CHECKO2REM-LABEL: test_ctlz_32_ignored | 343 ; CHECKO2REM-LABEL: test_ctlz_32_ignored |
| 350 ; CHECKO2REM-NOT: bsr | 344 ; CHECKO2REM-NOT: bsr |
| 351 | 345 |
| 352 define i64 @test_ctlz_64(i64 %x) { | 346 define i64 @test_ctlz_64(i64 %x) { |
| 353 entry: | 347 entry: |
| 354 %r = call i64 @llvm.ctlz.i64(i64 %x, i1 false) | 348 %r = call i64 @llvm.ctlz.i64(i64 %x, i1 false) |
| 355 ret i64 %r | 349 ret i64 %r |
| 356 } | 350 } |
| 357 ; CHECKO2REM-LABEL: test_ctlz_64 | 351 ; CHECKO2REM-LABEL: test_ctlz_64 |
| 358 ; CHECK-LABEL: test_ctlz_64 | 352 ; CHECK-LABEL: test_ctlz_64 |
| 359 ; CHECK: bsr [[REG_TMP1:e.*]], {{.*}} | 353 ; CHECK: bsr [[REG_TMP1:e.*]],{{.*}} |
| 360 ; CHECK: mov [[REG_RES1:e.*]], 63 | 354 ; CHECK: mov [[REG_RES1:e.*]],0x3f |
| 361 ; CHECK: cmovne [[REG_RES1]], [[REG_TMP1]] | 355 ; CHECK: cmovne [[REG_RES1]],[[REG_TMP1]] |
| 362 ; CHECK: xor [[REG_RES1]], 31 | 356 ; CHECK: xor [[REG_RES1]],0x1f |
| 363 ; CHECK: add [[REG_RES1]], 32 | 357 ; CHECK: add [[REG_RES1]],0x20 |
| 364 ; CHECK: bsr [[REG_RES2:e.*]], {{.*}} | 358 ; CHECK: bsr [[REG_RES2:e.*]],{{.*}} |
| 365 ; CHECK: xor [[REG_RES2]], 31 | 359 ; CHECK: xor [[REG_RES2]],0x1f |
| 366 ; CHECK: test [[REG_UPPER:.*]], [[REG_UPPER]] | 360 ; CHECK: test [[REG_UPPER:.*]],[[REG_UPPER]] |
| 367 ; CHECK: cmove [[REG_RES2]], [[REG_RES1]] | 361 ; CHECK: cmove [[REG_RES2]],[[REG_RES1]] |
| 368 ; CHECK: mov {{.*}}, 0 | 362 ; CHECK: mov {{.*}},0x0 |
| 369 | 363 |
| 370 define i32 @test_ctlz_64_const(i64 %x) { | 364 define i32 @test_ctlz_64_const(i64 %x) { |
| 371 entry: | 365 entry: |
| 372 %r = call i64 @llvm.ctlz.i64(i64 123456789012, i1 false) | 366 %r = call i64 @llvm.ctlz.i64(i64 123456789012, i1 false) |
| 373 %r2 = trunc i64 %r to i32 | 367 %r2 = trunc i64 %r to i32 |
| 374 ret i32 %r2 | 368 ret i32 %r2 |
| 375 } | 369 } |
| 376 ; CHECK-LABEL: test_ctlz_64_const | 370 ; CHECK-LABEL: test_ctlz_64_const |
| 377 ; CHECK: bsr e{{.*}}, {{.*}}e{{.*}} | 371 ; CHECK: bsr e{{.*}},{{.*}}e{{.*}} |
| 378 ; CHECK: bsr e{{.*}}, {{.*}}e{{.*}} | 372 ; CHECK: bsr e{{.*}},{{.*}}e{{.*}} |
| 379 | 373 |
| 380 | 374 |
| 381 define i32 @test_ctlz_64_ignored(i64 %x) { | 375 define i32 @test_ctlz_64_ignored(i64 %x) { |
| 382 entry: | 376 entry: |
| 383 %ignored = call i64 @llvm.ctlz.i64(i64 1234567890, i1 false) | 377 %ignored = call i64 @llvm.ctlz.i64(i64 1234567890, i1 false) |
| 384 ret i32 2 | 378 ret i32 2 |
| 385 } | 379 } |
| 386 ; CHECKO2REM-LABEL: test_ctlz_64_ignored | 380 ; CHECKO2REM-LABEL: test_ctlz_64_ignored |
| 387 ; CHECKO2REM-NOT: bsr | 381 ; CHECKO2REM-NOT: bsr |
| 388 | 382 |
| 389 define i32 @test_cttz_32(i32 %x) { | 383 define i32 @test_cttz_32(i32 %x) { |
| 390 entry: | 384 entry: |
| 391 %r = call i32 @llvm.cttz.i32(i32 %x, i1 false) | 385 %r = call i32 @llvm.cttz.i32(i32 %x, i1 false) |
| 392 ret i32 %r | 386 ret i32 %r |
| 393 } | 387 } |
| 394 ; CHECK-LABEL: test_cttz_32 | 388 ; CHECK-LABEL: test_cttz_32 |
| 395 ; CHECK: bsf [[REG_IF_NOTZERO:e.*]], {{.*}} | 389 ; CHECK: bsf [[REG_IF_NOTZERO:e.*]],{{.*}} |
| 396 ; CHECK: mov [[REG_IF_ZERO:e.*]], 32 | 390 ; CHECK: mov [[REG_IF_ZERO:e.*]],0x20 |
| 397 ; CHECK: cmovne [[REG_IF_ZERO]], [[REG_IF_NOTZERO]] | 391 ; CHECK: cmovne [[REG_IF_ZERO]],[[REG_IF_NOTZERO]] |
| 398 | 392 |
| 399 define i64 @test_cttz_64(i64 %x) { | 393 define i64 @test_cttz_64(i64 %x) { |
| 400 entry: | 394 entry: |
| 401 %r = call i64 @llvm.cttz.i64(i64 %x, i1 false) | 395 %r = call i64 @llvm.cttz.i64(i64 %x, i1 false) |
| 402 ret i64 %r | 396 ret i64 %r |
| 403 } | 397 } |
| 404 ; CHECK-LABEL: test_cttz_64 | 398 ; CHECK-LABEL: test_cttz_64 |
| 405 ; CHECK: bsf [[REG_IF_NOTZERO:e.*]], {{.*}} | 399 ; CHECK: bsf [[REG_IF_NOTZERO:e.*]],{{.*}} |
| 406 ; CHECK: mov [[REG_RES1:e.*]], 32 | 400 ; CHECK: mov [[REG_RES1:e.*]],0x20 |
| 407 ; CHECK: cmovne [[REG_RES1]], [[REG_IF_NOTZERO]] | 401 ; CHECK: cmovne [[REG_RES1]],[[REG_IF_NOTZERO]] |
| 408 ; CHECK: add [[REG_RES1]], 32 | 402 ; CHECK: add [[REG_RES1]],0x20 |
| 409 ; CHECK: bsf [[REG_RES2:e.*]], [[REG_LOWER:.*]] | 403 ; CHECK: bsf [[REG_RES2:e.*]],[[REG_LOWER:.*]] |
| 410 ; CHECK: test [[REG_LOWER]], [[REG_LOWER]] | 404 ; CHECK: test [[REG_LOWER]],[[REG_LOWER]] |
| 411 ; CHECK: cmove [[REG_RES2]], [[REG_RES1]] | 405 ; CHECK: cmove [[REG_RES2]],[[REG_RES1]] |
| 412 ; CHECK: mov {{.*}}, 0 | 406 ; CHECK: mov {{.*}},0x0 |
| 413 | 407 |
| 414 define i32 @test_popcount_32(i32 %x) { | 408 define i32 @test_popcount_32(i32 %x) { |
| 415 entry: | 409 entry: |
| 416 %r = call i32 @llvm.ctpop.i32(i32 %x) | 410 %r = call i32 @llvm.ctpop.i32(i32 %x) |
| 417 ret i32 %r | 411 ret i32 %r |
| 418 } | 412 } |
| 419 ; CHECK-LABEL: test_popcount_32 | 413 ; CHECK-LABEL: test_popcount_32 |
| 420 ; CHECK: call __popcountsi2 | 414 ; CHECK: call {{.*}} R_{{.*}} __popcountsi2 |
| 421 | 415 |
| 422 define i64 @test_popcount_64(i64 %x) { | 416 define i64 @test_popcount_64(i64 %x) { |
| 423 entry: | 417 entry: |
| 424 %r = call i64 @llvm.ctpop.i64(i64 %x) | 418 %r = call i64 @llvm.ctpop.i64(i64 %x) |
| 425 ret i64 %r | 419 ret i64 %r |
| 426 } | 420 } |
| 427 ; CHECK-LABEL: test_popcount_64 | 421 ; CHECK-LABEL: test_popcount_64 |
| 428 ; CHECK: call __popcountdi2 | 422 ; CHECK: call {{.*}} R_{{.*}} __popcountdi2 |
| 429 ; __popcountdi2 only returns a 32-bit result, so clear the upper bits of | 423 ; __popcountdi2 only returns a 32-bit result, so clear the upper bits of |
| 430 ; the return value just in case. | 424 ; the return value just in case. |
| 431 ; CHECK: mov {{.*}}, 0 | 425 ; CHECK: mov {{.*}},0x0 |
| 432 | 426 |
| 433 | 427 |
| 434 define i32 @test_popcount_64_ret_i32(i64 %x) { | 428 define i32 @test_popcount_64_ret_i32(i64 %x) { |
| 435 entry: | 429 entry: |
| 436 %r_i64 = call i64 @llvm.ctpop.i64(i64 %x) | 430 %r_i64 = call i64 @llvm.ctpop.i64(i64 %x) |
| 437 %r = trunc i64 %r_i64 to i32 | 431 %r = trunc i64 %r_i64 to i32 |
| 438 ret i32 %r | 432 ret i32 %r |
| 439 } | 433 } |
| 440 ; If there is a trunc, then the mov {{.*}}, 0 is dead and gets optimized out. | 434 ; If there is a trunc, then the mov {{.*}}, 0 is dead and gets optimized out. |
| 441 ; CHECKO2REM-LABEL: test_popcount_64_ret_i32 | 435 ; CHECKO2REM-LABEL: test_popcount_64_ret_i32 |
| 442 ; CHECKO2REM: call __popcountdi2 | 436 ; CHECKO2REM: call {{.*}} R_{{.*}} __popcountdi2 |
| 443 ; CHECKO2REM-NOT: mov {{.*}}, 0 | 437 ; CHECKO2REM-NOT: mov {{.*}}, 0 |
| 444 | 438 |
| 445 define void @test_stacksave_noalloca() { | 439 define void @test_stacksave_noalloca() { |
| 446 entry: | 440 entry: |
| 447 %sp = call i8* @llvm.stacksave() | 441 %sp = call i8* @llvm.stacksave() |
| 448 call void @llvm.stackrestore(i8* %sp) | 442 call void @llvm.stackrestore(i8* %sp) |
| 449 ret void | 443 ret void |
| 450 } | 444 } |
| 451 ; CHECK-LABEL: test_stacksave_noalloca | 445 ; CHECK-LABEL: test_stacksave_noalloca |
| 452 ; CHECK: mov {{.*}}, esp | 446 ; CHECK: mov {{.*}},esp |
| 453 ; CHECK: mov esp, {{.*}} | 447 ; CHECK: mov esp,{{.*}} |
| 454 | 448 |
| 455 declare i32 @foo(i32 %x) | 449 declare i32 @foo(i32 %x) |
| 456 | 450 |
| 457 define void @test_stacksave_multiple(i32 %x) { | 451 define void @test_stacksave_multiple(i32 %x) { |
| 458 entry: | 452 entry: |
| 459 %x_4 = mul i32 %x, 4 | 453 %x_4 = mul i32 %x, 4 |
| 460 %sp1 = call i8* @llvm.stacksave() | 454 %sp1 = call i8* @llvm.stacksave() |
| 461 %tmp1 = alloca i8, i32 %x_4, align 4 | 455 %tmp1 = alloca i8, i32 %x_4, align 4 |
| 462 | 456 |
| 463 %sp2 = call i8* @llvm.stacksave() | 457 %sp2 = call i8* @llvm.stacksave() |
| (...skipping 11 matching lines...) Expand all Loading... |
| 475 store i32 %x, i32* %__10, align 1 | 469 store i32 %x, i32* %__10, align 1 |
| 476 | 470 |
| 477 %__11 = bitcast i8* %tmp3 to i32* | 471 %__11 = bitcast i8* %tmp3 to i32* |
| 478 store i32 %x, i32* %__11, align 1 | 472 store i32 %x, i32* %__11, align 1 |
| 479 | 473 |
| 480 call void @llvm.stackrestore(i8* %sp1) | 474 call void @llvm.stackrestore(i8* %sp1) |
| 481 ret void | 475 ret void |
| 482 } | 476 } |
| 483 ; CHECK-LABEL: test_stacksave_multiple | 477 ; CHECK-LABEL: test_stacksave_multiple |
| 484 ; At least 3 copies of esp, but probably more from having to do the allocas. | 478 ; At least 3 copies of esp, but probably more from having to do the allocas. |
| 485 ; CHECK: mov {{.*}}, esp | 479 ; CHECK: mov {{.*}},esp |
| 486 ; CHECK: mov {{.*}}, esp | 480 ; CHECK: mov {{.*}},esp |
| 487 ; CHECK: mov {{.*}}, esp | 481 ; CHECK: mov {{.*}},esp |
| 488 ; CHECK: mov esp, {{.*}} | 482 ; CHECK: mov esp,{{.*}} |
| OLD | NEW |