| ; RUN: llc -mtriple=hexagon -stop-after=hexagon-isel -o - %s | FileCheck %s |
| |
| ; A bit-reverse load accesses the base pointer with its low 16 bits reversed, |
| ; and post-increments the base pointer by the modifier value. For a chain of |
| ; bit-reverse loads the offset accessed by a load is therefore the bit-reverse |
| ; of the sum of the modifiers of the preceding loads in the chain. Check that |
| ; the offset of the memory operand is set accordingly, so that alias analysis |
| ; does not break the dependence between an aliasing store and the loads. |
| |
| @buf = global [256 x i8] zeroinitializer, align 65536 |
| |
| ; CHECK-LABEL: name: {{.*}}brev_chain |
| ; CHECK: L2_loadrb_pbr{{.*}}:: (load (s32) from @buf) |
| ; CHECK: L2_loadrb_pbr{{.*}}:: (load (s32) from @buf + 128) |
| ; CHECK: L2_loadrb_pbr{{.*}}:: (load (s32) from @buf + 64) |
| ; CHECK: L2_loadrb_pbr{{.*}}:: (load (s32) from @buf + 192) |
| define i8 @brev_chain() { |
| entry: |
| %v0 = tail call { i32, ptr } @llvm.hexagon.L2.loadrb.pbr(ptr @buf, i32 256) |
| %p0 = extractvalue { i32, ptr } %v0, 1 |
| %v1 = tail call { i32, ptr } @llvm.hexagon.L2.loadrb.pbr(ptr %p0, i32 256) |
| %p1 = extractvalue { i32, ptr } %v1, 1 |
| %v2 = tail call { i32, ptr } @llvm.hexagon.L2.loadrb.pbr(ptr %p1, i32 256) |
| %p2 = extractvalue { i32, ptr } %v2, 1 |
| %v3 = tail call { i32, ptr } @llvm.hexagon.L2.loadrb.pbr(ptr %p2, i32 256) |
| %r = extractvalue { i32, ptr } %v3, 0 |
| %t = trunc i32 %r to i8 |
| ret i8 %t |
| } |
| |
| ; The offset of the second load is not known, because the modifier of the |
| ; first load is not a constant. |
| |
| ; CHECK-LABEL: name: {{.*}}brev_unknown_mod |
| ; CHECK: L2_loadrb_pbr{{.*}}:: (load (s32) from @buf) |
| ; CHECK: L2_loadrb_pbr{{.*}}:: (load (s32)) |
| define i8 @brev_unknown_mod(i32 %m) { |
| entry: |
| %v0 = tail call { i32, ptr } @llvm.hexagon.L2.loadrb.pbr(ptr @buf, i32 %m) |
| %p0 = extractvalue { i32, ptr } %v0, 1 |
| %v1 = tail call { i32, ptr } @llvm.hexagon.L2.loadrb.pbr(ptr %p0, i32 256) |
| %r = extractvalue { i32, ptr } %v1, 0 |
| %t = trunc i32 %r to i8 |
| ret i8 %t |
| } |
| |
| ; Only the low 16 bits of the base pointer take part in the bit-reverse, so |
| ; the offset of the second load is not known if the sum of the modifiers does |
| ; not fit in 16 unsigned bits. |
| |
| ; CHECK-LABEL: name: {{.*}}brev_wide_mod |
| ; CHECK: L2_loadrb_pbr{{.*}}:: (load (s32) from @buf) |
| ; CHECK: L2_loadrb_pbr{{.*}}:: (load (s32)) |
| define i8 @brev_wide_mod() { |
| entry: |
| %v0 = tail call { i32, ptr } @llvm.hexagon.L2.loadrb.pbr(ptr @buf, i32 65536) |
| %p0 = extractvalue { i32, ptr } %v0, 1 |
| %v1 = tail call { i32, ptr } @llvm.hexagon.L2.loadrb.pbr(ptr %p0, i32 256) |
| %r = extractvalue { i32, ptr } %v1, 0 |
| %t = trunc i32 %r to i8 |
| ret i8 %t |
| } |
| |
| ; A negative modifier makes the offset of the second load unknown as well. |
| |
| ; CHECK-LABEL: name: {{.*}}brev_negative_mod |
| ; CHECK: L2_loadrb_pbr{{.*}}:: (load (s32) from @buf) |
| ; CHECK: L2_loadrb_pbr{{.*}}:: (load (s32)) |
| define i8 @brev_negative_mod() { |
| entry: |
| %v0 = tail call { i32, ptr } @llvm.hexagon.L2.loadrb.pbr(ptr @buf, i32 -256) |
| %p0 = extractvalue { i32, ptr } %v0, 1 |
| %v1 = tail call { i32, ptr } @llvm.hexagon.L2.loadrb.pbr(ptr %p0, i32 256) |
| %r = extractvalue { i32, ptr } %v1, 0 |
| %t = trunc i32 %r to i8 |
| ret i8 %t |
| } |
| |
| declare { i32, ptr } @llvm.hexagon.L2.loadrb.pbr(ptr, i32) |