diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index b5c01eafcf108..45918232e3a70 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -13885,6 +13885,10 @@ bool ARMTargetLowering::shouldFoldConstantShiftPairToMask( N->getOperand(0).getOpcode() == ISD::SHL)) && "Expected shift-shift mask"); + // Don't allow multiuse shift folding with the same shift amount. + if (!N->getOperand(0)->hasOneUse()) + return false; + if (!Subtarget->isThumb1Only()) return true; diff --git a/llvm/test/CodeGen/ARM/combine-movc-sub.ll b/llvm/test/CodeGen/ARM/combine-movc-sub.ll index ca5d089443542..0aaab83b51ce9 100644 --- a/llvm/test/CodeGen/ARM/combine-movc-sub.ll +++ b/llvm/test/CodeGen/ARM/combine-movc-sub.ll @@ -25,15 +25,15 @@ declare void @foo(ptr, ptr) define hidden fastcc ptr @test(ptr %Search, ptr %ClauseList, i32 %Level, ptr nocapture %New) { ; CHECK-LABEL: test: ; CHECK: @ %bb.0: @ %entry -; CHECK-NEXT: push.w {r4, r5, r6, r7, r8, r9, lr} -; CHECK-NEXT: sub sp, #4 -; CHECK-NEXT: sub.w r7, r2, #32 +; CHECK-NEXT: push.w {r4, r5, r6, r7, r8, r9, r10, lr} +; CHECK-NEXT: sub.w r9, r2, #32 ; CHECK-NEXT: mov r8, r0 ; CHECK-NEXT: movs r0, #1 ; CHECK-NEXT: mov r4, r2 -; CHECK-NEXT: add.w r6, r0, r7, lsr #5 +; CHECK-NEXT: add.w r6, r0, r9, lsr #5 ; CHECK-NEXT: mov r5, r1 -; CHECK-NEXT: mov.w r9, #0 +; CHECK-NEXT: lsr.w r7, r9, #5 +; CHECK-NEXT: mov.w r10, #0 ; CHECK-NEXT: b .LBB0_2 ; CHECK-NEXT: .LBB0_1: @ %for.inc ; CHECK-NEXT: @ in Loop: Header=BB0_2 Depth=1 @@ -47,7 +47,7 @@ define hidden fastcc ptr @test(ptr %Search, ptr %ClauseList, i32 %Level, ptr noc ; CHECK-NEXT: add.w r0, r0, r6, lsl #2 ; CHECK-NEXT: ldr r0, [r0, #40] ; CHECK-NEXT: it hi -; CHECK-NEXT: andhi r2, r7, #31 +; CHECK-NEXT: subhi.w r2, r9, r7, lsl #5 ; CHECK-NEXT: lsrs r0, r2 ; CHECK-NEXT: lsls r0, r0, #31 ; CHECK-NEXT: beq .LBB0_1 @@ -55,7 +55,7 @@ define hidden fastcc ptr @test(ptr %Search, ptr %ClauseList, i32 %Level, ptr noc ; CHECK-NEXT: @ in Loop: Header=BB0_2 Depth=1 ; CHECK-NEXT: mov r0, r8 ; CHECK-NEXT: bl foo -; CHECK-NEXT: str.w r9, [r5, #4] +; CHECK-NEXT: str.w r10, [r5, #4] ; CHECK-NEXT: b .LBB0_1 entry: %cmp4.i.i = icmp ugt i32 %Level, 31 diff --git a/llvm/test/CodeGen/ARM/dagcombine-ld-op-st.ll b/llvm/test/CodeGen/ARM/dagcombine-ld-op-st.ll index 6819af3ba3e26..4025a32655a6f 100644 --- a/llvm/test/CodeGen/ARM/dagcombine-ld-op-st.ll +++ b/llvm/test/CodeGen/ARM/dagcombine-ld-op-st.ll @@ -41,10 +41,11 @@ define i16 @test(ptr %p1) { ; ; CHECK-BE-NORMAL-LABEL: test: ; CHECK-BE-NORMAL: @ %bb.0: @ %entry -; CHECK-BE-NORMAL-NEXT: ldrh r1, [r0] +; CHECK-BE-NORMAL-NEXT: ldr r1, [r0] ; CHECK-BE-NORMAL-NEXT: movw r2, #65534 -; CHECK-BE-NORMAL-NEXT: orr r1, r1, r2 -; CHECK-BE-NORMAL-NEXT: strh r1, [r0] +; CHECK-BE-NORMAL-NEXT: orr r2, r2, r1, lsr #16 +; CHECK-BE-NORMAL-NEXT: pkhbt r1, r1, r2, lsl #16 +; CHECK-BE-NORMAL-NEXT: str r1, [r0] ; CHECK-BE-NORMAL-NEXT: mov r0, #0 ; CHECK-BE-NORMAL-NEXT: bx lr ; diff --git a/llvm/test/CodeGen/ARM/illegal-bitfield-loadstore.ll b/llvm/test/CodeGen/ARM/illegal-bitfield-loadstore.ll index 5dbf8dd86b891..1627e4fab6423 100644 --- a/llvm/test/CodeGen/ARM/illegal-bitfield-loadstore.ll +++ b/llvm/test/CodeGen/ARM/illegal-bitfield-loadstore.ll @@ -90,16 +90,16 @@ define void @i56_or(ptr %a) { ; ; BE-LABEL: i56_or: ; BE: @ %bb.0: -; BE-NEXT: mov r1, r0 -; BE-NEXT: ldr r0, [r0] -; BE-NEXT: ldrh r2, [r1, #4]! -; BE-NEXT: ldrb r3, [r1, #2] +; BE-NEXT: ldr r1, [r0] +; BE-NEXT: strb r1, [r0, #3] +; BE-NEXT: ldrh r2, [r0, #4]! +; BE-NEXT: ldrb r3, [r0, #2] ; BE-NEXT: orr r2, r3, r2, lsl #8 -; BE-NEXT: orr r0, r2, r0, lsl #24 -; BE-NEXT: orr r0, r0, #384 -; BE-NEXT: strb r0, [r1, #2] -; BE-NEXT: lsr r0, r0, #8 -; BE-NEXT: strh r0, [r1] +; BE-NEXT: orr r1, r2, r1, lsl #24 +; BE-NEXT: orr r1, r1, #384 +; BE-NEXT: strb r1, [r0, #2] +; BE-NEXT: lsr r1, r1, #8 +; BE-NEXT: strh r1, [r0] ; BE-NEXT: mov pc, lr %aa = load i56, ptr %a %b = or i56 %aa, 384 @@ -118,11 +118,14 @@ define void @i56_and_or(ptr %a) { ; ; BE-LABEL: i56_and_or: ; BE: @ %bb.0: -; BE-NEXT: ldrh r1, [r0, #4]! -; BE-NEXT: mov r2, #128 -; BE-NEXT: orr r1, r1, #1 -; BE-NEXT: strb r2, [r0, #2] -; BE-NEXT: strh r1, [r0] +; BE-NEXT: mov r1, r0 +; BE-NEXT: mov r3, #128 +; BE-NEXT: ldrh r2, [r1, #4]! +; BE-NEXT: strb r3, [r1, #2] +; BE-NEXT: ldr r3, [r0] +; BE-NEXT: strb r3, [r0, #3] +; BE-NEXT: orr r0, r2, #1 +; BE-NEXT: strh r0, [r1] ; BE-NEXT: mov pc, lr %b = load i56, ptr %a, align 1 @@ -143,9 +146,11 @@ define void @i56_insert_bit(ptr %a, i1 zeroext %bit) { ; ; BE-LABEL: i56_insert_bit: ; BE: @ %bb.0: -; BE-NEXT: ldrh r2, [r0, #4]! +; BE-NEXT: ldr r2, [r0] ; BE-NEXT: mov r3, #57088 +; BE-NEXT: strb r2, [r0, #3] ; BE-NEXT: orr r3, r3, #16711680 +; BE-NEXT: ldrh r2, [r0, #4]! ; BE-NEXT: and r2, r3, r2, lsl #8 ; BE-NEXT: orr r1, r2, r1, lsl #13 ; BE-NEXT: lsr r1, r1, #8 diff --git a/llvm/test/CodeGen/ARM/rotate-add.ll b/llvm/test/CodeGen/ARM/rotate-add.ll index fd3055e5e2725..4ae7fcf6fac00 100644 --- a/llvm/test/CodeGen/ARM/rotate-add.ll +++ b/llvm/test/CodeGen/ARM/rotate-add.ll @@ -124,9 +124,9 @@ define i64 @test_rotl_udiv_special_case(i64 %i) { ; CHECK-NEXT: ldr r12, .LCPI8_0 ; CHECK-NEXT: adc lr, r2, #0 ; CHECK-NEXT: umull r3, r2, lr, r12 -; CHECK-NEXT: bic r3, r2, #1 -; CHECK-NEXT: add r2, r3, r2, lsr #1 ; CHECK-NEXT: ldr r3, .LCPI8_1 +; CHECK-NEXT: lsr r2, r2, #1 +; CHECK-NEXT: add r2, r2, r2, lsl #1 ; CHECK-NEXT: sub r2, lr, r2 ; CHECK-NEXT: subs r0, r0, r2 ; CHECK-NEXT: sbc r1, r1, #0 diff --git a/llvm/test/CodeGen/ARM/ushlsat.ll b/llvm/test/CodeGen/ARM/ushlsat.ll new file mode 100644 index 0000000000000..149e703430c45 --- /dev/null +++ b/llvm/test/CodeGen/ARM/ushlsat.ll @@ -0,0 +1,62 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=thumbv7m-eabi %s -o - | FileCheck %s --check-prefix V7M +; RUN: llc -mtriple=armv7a-eabi %s -o - | FileCheck %s --check-prefix V7A +; RUN: llc -mtriple=thumbv7a-eabi %s -o - | FileCheck %s --check-prefix V7A-T +; RUN: llc -mtriple=armv6m-eabi %s -o - | FileCheck %s --check-prefix V6M + +; Do not fold shlsat -> shl. +define i16 @combine_shlsat_to_shl_no_fold(i16 %x) nounwind { +; V7M-LABEL: combine_shlsat_to_shl_no_fold: +; V7M: @ %bb.0: +; V7M-NEXT: movs r1, #0 +; V7M-NEXT: movt r1, #16383 +; V7M-NEXT: and.w r0, r1, r0, lsl #14 +; V7M-NEXT: lsls r1, r0, #3 +; V7M-NEXT: cmp.w r0, r1, lsr #3 +; V7M-NEXT: it ne +; V7M-NEXT: movne.w r1, #-1 +; V7M-NEXT: lsrs r0, r1, #16 +; V7M-NEXT: bx lr +; +; V7A-LABEL: combine_shlsat_to_shl_no_fold: +; V7A: @ %bb.0: +; V7A-NEXT: movw r1, #0 +; V7A-NEXT: movt r1, #16383 +; V7A-NEXT: and r0, r1, r0, lsl #14 +; V7A-NEXT: lsl r1, r0, #3 +; V7A-NEXT: cmp r0, r1, lsr #3 +; V7A-NEXT: mvnne r1, #0 +; V7A-NEXT: lsr r0, r1, #16 +; V7A-NEXT: bx lr +; +; V7A-T-LABEL: combine_shlsat_to_shl_no_fold: +; V7A-T: @ %bb.0: +; V7A-T-NEXT: movs r1, #0 +; V7A-T-NEXT: movt r1, #16383 +; V7A-T-NEXT: and.w r0, r1, r0, lsl #14 +; V7A-T-NEXT: lsls r1, r0, #3 +; V7A-T-NEXT: cmp.w r0, r1, lsr #3 +; V7A-T-NEXT: it ne +; V7A-T-NEXT: movne.w r1, #-1 +; V7A-T-NEXT: lsrs r0, r1, #16 +; V7A-T-NEXT: bx lr +; +; V6M-LABEL: combine_shlsat_to_shl_no_fold: +; V6M: @ %bb.0: +; V6M-NEXT: lsls r0, r0, #16 +; V6M-NEXT: lsrs r0, r0, #18 +; V6M-NEXT: lsls r1, r0, #16 +; V6M-NEXT: lsls r0, r0, #19 +; V6M-NEXT: lsrs r2, r0, #3 +; V6M-NEXT: cmp r1, r2 +; V6M-NEXT: beq .LBB0_2 +; V6M-NEXT: @ %bb.1: +; V6M-NEXT: movs r0, #0 +; V6M-NEXT: mvns r0, r0 +; V6M-NEXT: .LBB0_2: +; V6M-NEXT: lsrs r0, r0, #16 +; V6M-NEXT: bx lr + %x2 = lshr i16 %x, 2 + %tmp = call i16 @llvm.ushl.sat.i16(i16 %x2, i16 3) + ret i16 %tmp +}