Index: llvm/lib/Target/ARM/ARMInstrInfo.td =================================================================== --- llvm/lib/Target/ARM/ARMInstrInfo.td +++ llvm/lib/Target/ARM/ARMInstrInfo.td @@ -380,6 +380,11 @@ return CurDAG->getTargetConstant(~(int)N->getZExtValue(), SDLoc(N), MVT::i32); }]>; +// asr_imm_XFORM - Returns a shift immediate with bit {5} set to 1 +def asr_imm_XFORM : SDNodeXFormgetTargetConstant(0x20 | N->getZExtValue(), SDLoc(N), MVT:: i32); +}]>; + /// imm16_31 predicate - True if the 32-bit immediate is in the range [16,31]. def imm16_31 : ImmLeaf= 16 && (int32_t)Imm < 32; @@ -446,6 +451,8 @@ def imm_even : ImmLeaf; def imm_odd : ImmLeaf; +def asr_imm : ImmLeaf 0 && Imm <= 32; }], asr_imm_XFORM>; + //===----------------------------------------------------------------------===// // NEON/MVE pattern fragments // @@ -4081,6 +4088,15 @@ (SSAT16 imm1_16:$pos, GPRnopc:$a)>; def : ARMV6Pat<(int_arm_usat16 GPRnopc:$a, imm0_15:$pos), (USAT16 imm0_15:$pos, GPRnopc:$a)>; +def : ARMV6Pat<(int_arm_ssat (shl GPRnopc:$a, imm0_31:$shft), imm1_32:$pos), + (SSAT imm1_32:$pos, GPRnopc:$a, imm0_31:$shft)>; +def : ARMV6Pat<(int_arm_ssat (sra GPRnopc:$a, asr_imm:$shft), imm1_32:$pos), + (SSAT imm1_32:$pos, GPRnopc:$a, asr_imm:$shft)>; +def : ARMV6Pat<(int_arm_usat (shl GPRnopc:$a, imm0_31:$shft), imm0_31:$pos), + (USAT imm0_31:$pos, GPRnopc:$a, imm0_31:$shft)>; +def : ARMV6Pat<(int_arm_usat (sra GPRnopc:$a, asr_imm:$shft), imm0_31:$pos), + (USAT imm0_31:$pos, GPRnopc:$a, asr_imm:$shft)>; + //===----------------------------------------------------------------------===// // Bitwise Instructions. Index: llvm/lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- llvm/lib/Target/ARM/ARMInstrThumb2.td +++ llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -2636,6 +2636,15 @@ (t2SSAT16 imm1_16:$pos, GPR:$a)>; def : T2Pat<(int_arm_usat16 GPR:$a, imm0_15:$pos), (t2USAT16 imm0_15:$pos, GPR:$a)>; +def : T2Pat<(int_arm_ssat (shl GPRnopc:$a, imm0_31:$shft), imm1_32:$pos), + (t2SSAT imm1_32:$pos, GPRnopc:$a, imm0_31:$shft)>; +def : T2Pat<(int_arm_ssat (sra GPRnopc:$a, asr_imm:$shft), imm1_32:$pos), + (t2SSAT imm1_32:$pos, GPRnopc:$a, asr_imm:$shft)>; +def : T2Pat<(int_arm_usat (shl GPRnopc:$a, imm0_31:$shft), imm0_31:$pos), + (t2USAT imm0_31:$pos, GPRnopc:$a, imm0_31:$shft)>; +def : T2Pat<(int_arm_usat (sra GPRnopc:$a, asr_imm:$shft), imm0_31:$pos), + (t2USAT imm0_31:$pos, GPRnopc:$a, asr_imm:$shft)>; + //===----------------------------------------------------------------------===// // Shift and rotate Instructions. Index: llvm/test/CodeGen/ARM/ssat-with-shift.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/ARM/ssat-with-shift.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=armv6-eabi %s -o - | FileCheck %s +; RUN: llc -mtriple=thumbv8.1m.main-arm-none-eabi -mattr=+dsp %s -o - | FileCheck %s + +define arm_aapcs_vfpcc i32 @ssat_lsl(i32 %num){ +; CHECK-LABEL: ssat_lsl +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: ssat r0, #8, r0, lsl #7 +; CHECK-NEXT: bx lr +entry: + %shl = shl i32 %num, 7 + %0 = tail call i32 @llvm.arm.ssat(i32 %shl, i32 8) + ret i32 %0 +} + +define arm_aapcs_vfpcc i32 @ssat_asr(i32 %num){ +; CHECK-LABEL: ssat_asr +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: ssat r0, #8, r0, asr #7 +; CHECK-NEXT: bx lr +entry: + %shr = ashr i32 %num, 7 + %0 = tail call i32 @llvm.arm.ssat(i32 %shr, i32 8) + ret i32 %0 +} + +declare i32 @llvm.arm.ssat(i32, i32) Index: llvm/test/CodeGen/ARM/usat-with-shift.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/ARM/usat-with-shift.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=armv6-eabi %s -o - | FileCheck %s +; RUN: llc -mtriple=thumbv8.1m.main-arm-none-eabi -mattr=+dsp %s -o - | FileCheck %s + +define arm_aapcs_vfpcc i32 @usat_lsl(i32 %num){ +; CHECK-LABEL: usat_lsl +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: usat r0, #7, r0, lsl #2 +; CHECK-NEXT: bx lr +entry: + %shl = shl i32 %num, 2 + %0 = tail call i32 @llvm.arm.usat(i32 %shl, i32 7) + ret i32 %0 +} + +define arm_aapcs_vfpcc i32 @usat_asr(i32 %num){ +; CHECK-LABEL: usat_asr +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: usat r0, #7, r0, asr #2 +; CHECK-NEXT: bx lr +entry: + %shr = ashr i32 %num, 2 + %0 = tail call i32 @llvm.arm.usat(i32 %shr, i32 7) + ret i32 %0 +} + +declare i32 @llvm.arm.usat(i32, i32)