diff options
author | Tim Northover <tnorthover@apple.com> | 2014-04-03 15:10:35 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2014-04-03 15:10:35 +0000 |
commit | 01b4aa94371345be8e19129ccd9c6814f9c0e6aa (patch) | |
tree | 03ee37a4fd0f15c9b5dfcc2baff4896eb1679263 /llvm/test | |
parent | 0dcccf7bf3c1c8dfcfb8a92940c3240f8a2f7749 (diff) | |
download | bcm5719-llvm-01b4aa94371345be8e19129ccd9c6814f9c0e6aa.tar.gz bcm5719-llvm-01b4aa94371345be8e19129ccd9c6814f9c0e6aa.zip |
ARM: tell LLVM about zext properties of ldrexb/ldrexh
Implementing this via ComputeMaskedBits has two advantages:
+ It actually works. DAGISel doesn't deal with the chains properly
in the previous pattern-based solution, so they never trigger.
+ The information can be used in other DAG combines, as well as the
trivial "get rid of truncs". For example if the trunc is in a
different basic block.
rdar://problem/16227836
llvm-svn: 205540
Diffstat (limited to 'llvm/test')
-rw-r--r-- | llvm/test/CodeGen/ARM/atomic-ops-v8.ll | 22 | ||||
-rw-r--r-- | llvm/test/CodeGen/ARM/ldaex-stlex.ll | 12 | ||||
-rw-r--r-- | llvm/test/CodeGen/ARM/ldstrex.ll | 28 |
3 files changed, 42 insertions, 20 deletions
diff --git a/llvm/test/CodeGen/ARM/atomic-ops-v8.ll b/llvm/test/CodeGen/ARM/atomic-ops-v8.ll index 00f9006c155..7922e222030 100644 --- a/llvm/test/CodeGen/ARM/atomic-ops-v8.ll +++ b/llvm/test/CodeGen/ARM/atomic-ops-v8.ll @@ -805,8 +805,8 @@ define i8 @test_atomic_load_umin_i8(i8 zeroext %offset) nounwind { ; CHECK: ldrexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]] ; r0 below is a reasonable guess but could change: it certainly comes into the ; function there. -; CHECK-NEXT: uxtb r[[OLDX]], r[[OLD]] -; CHECK-NEXT: cmp r[[OLDX]], r0 +; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0 +; CHECK-NEXT: cmp r[[OLD]], r0 ; Thumb mode: it ls ; CHECK: movls r[[NEW]], r[[OLD]] ; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]] @@ -831,8 +831,8 @@ define i16 @test_atomic_load_umin_i16(i16 zeroext %offset) nounwind { ; CHECK: ldaexh r[[OLD:[0-9]+]], {{.*}}[[ADDR]] ; r0 below is a reasonable guess but could change: it certainly comes into the ; function there. -; CHECK-NEXT: uxth r[[OLDX]], r[[OLD]] -; CHECK-NEXT: cmp r[[OLDX]], r0 +; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0 +; CHECK-NEXT: cmp r[[OLD]], r0 ; Thumb mode: it ls ; CHECK: movls r[[NEW]], r[[OLD]] ; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]] @@ -919,8 +919,8 @@ define i8 @test_atomic_load_umax_i8(i8 zeroext %offset) nounwind { ; CHECK: ldaexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]] ; r0 below is a reasonable guess but could change: it certainly comes into the ; function there. -; CHECK-NEXT: uxtb r[[OLDX:[0-9]+]], r[[OLD]] -; CHECK-NEXT: cmp r[[OLDX]], r0 +; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0 +; CHECK-NEXT: cmp r[[OLD]], r0 ; Thumb mode: it hi ; CHECK: movhi r[[NEW]], r[[OLD]] ; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]] @@ -945,8 +945,8 @@ define i16 @test_atomic_load_umax_i16(i16 zeroext %offset) nounwind { ; CHECK: ldrexh r[[OLD:[0-9]+]], {{.*}}[[ADDR]] ; r0 below is a reasonable guess but could change: it certainly comes into the ; function there. -; CHECK-NEXT: uxth r[[OLDX:[0-9]+]], r[[OLD]] -; CHECK-NEXT: cmp r[[OLDX]], r0 +; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0 +; CHECK-NEXT: cmp r[[OLD]], r0 ; Thumb mode: it hi ; CHECK: movhi r[[NEW]], r[[OLD]] ; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]] @@ -1033,8 +1033,7 @@ define i8 @test_atomic_cmpxchg_i8(i8 zeroext %wanted, i8 zeroext %new) nounwind ; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]] ; r0 below is a reasonable guess but could change: it certainly comes into the ; function there. -; CHECK-NEXT: uxtb r[[OLDX:[0-9]+]], r[[OLD]] -; CHECK-NEXT: cmp r[[OLDX]], r0 +; CHECK-NEXT: cmp r[[OLD]], r0 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_3 ; CHECK-NEXT: BB#2: ; As above, r1 is a reasonable guess. @@ -1060,8 +1059,7 @@ define i16 @test_atomic_cmpxchg_i16(i16 zeroext %wanted, i16 zeroext %new) nounw ; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]] ; r0 below is a reasonable guess but could change: it certainly comes into the ; function there. -; CHECK-NEXT: uxth r[[OLDX:[0-9]+]], r[[OLD]] -; CHECK-NEXT: cmp r[[OLDX]], r0 +; CHECK-NEXT: cmp r[[OLD]], r0 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_3 ; CHECK-NEXT: BB#2: ; As above, r1 is a reasonable guess. diff --git a/llvm/test/CodeGen/ARM/ldaex-stlex.ll b/llvm/test/CodeGen/ARM/ldaex-stlex.ll index f309f77fd5f..bfdfea33156 100644 --- a/llvm/test/CodeGen/ARM/ldaex-stlex.ll +++ b/llvm/test/CodeGen/ARM/ldaex-stlex.ll @@ -34,17 +34,21 @@ declare i32 @llvm.arm.stlexd(i32, i32, i8*) nounwind ; CHECK-LABEL: test_load_i8: ; CHECK: ldaexb r0, [r0] ; CHECK-NOT: uxtb -define i32 @test_load_i8(i8* %addr) { +; CHECK-NOT: and +define zeroext i8 @test_load_i8(i8* %addr) { %val = call i32 @llvm.arm.ldaex.p0i8(i8* %addr) - ret i32 %val + %val8 = trunc i32 %val to i8 + ret i8 %val8 } ; CHECK-LABEL: test_load_i16: ; CHECK: ldaexh r0, [r0] ; CHECK-NOT: uxth -define i32 @test_load_i16(i16* %addr) { +; CHECK-NOT: and +define zeroext i16 @test_load_i16(i16* %addr) { %val = call i32 @llvm.arm.ldaex.p0i16(i16* %addr) - ret i32 %val + %val16 = trunc i32 %val to i16 + ret i16 %val16 } ; CHECK-LABEL: test_load_i32: diff --git a/llvm/test/CodeGen/ARM/ldstrex.ll b/llvm/test/CodeGen/ARM/ldstrex.ll index 5eaae53da99..a40e255e83e 100644 --- a/llvm/test/CodeGen/ARM/ldstrex.ll +++ b/llvm/test/CodeGen/ARM/ldstrex.ll @@ -36,17 +36,21 @@ declare i32 @llvm.arm.strexd(i32, i32, i8*) nounwind ; CHECK-LABEL: test_load_i8: ; CHECK: ldrexb r0, [r0] ; CHECK-NOT: uxtb -define i32 @test_load_i8(i8* %addr) { +; CHECK-NOT: and +define zeroext i8 @test_load_i8(i8* %addr) { %val = call i32 @llvm.arm.ldrex.p0i8(i8* %addr) - ret i32 %val + %val8 = trunc i32 %val to i8 + ret i8 %val8 } ; CHECK-LABEL: test_load_i16: ; CHECK: ldrexh r0, [r0] ; CHECK-NOT: uxth -define i32 @test_load_i16(i16* %addr) { +; CHECK-NOT: and +define zeroext i16 @test_load_i16(i16* %addr) { %val = call i32 @llvm.arm.ldrex.p0i16(i16* %addr) - ret i32 %val + %val16 = trunc i32 %val to i16 + ret i16 %val16 } ; CHECK-LABEL: test_load_i32: @@ -137,3 +141,19 @@ define void @excl_addrmode() { ret void } + +; LLVM should know, even across basic blocks, that ldrex is setting the high +; bits of its i32 to 0. There should be no zero-extend operation. +define zeroext i8 @test_cross_block_zext_i8(i1 %tst, i8* %addr) { +; CHECK: test_cross_block_zext_i8: +; CHECK-NOT: uxtb +; CHECK-NOT: and +; CHECK: bx lr + %val = call i32 @llvm.arm.ldrex.p0i8(i8* %addr) + br i1 %tst, label %end, label %mid +mid: + ret i8 42 +end: + %val8 = trunc i32 %val to i8 + ret i8 %val8 +} |