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 @@ -84,6 +84,12 @@ return CurDAG->getTargetConstant(~N16bitSignExt, SDLoc(N), MVT::i32); }]>; +// t2_asr_imm - Returns immediate with bit {5} set to 1 +def t2_asr_imm_XFORM : SDNodeXFormgetTargetConstant(0x20 | N->getZExtValue(), SDLoc(N), + MVT:: i32); +}]>; + // t2_so_imm - Match a 32-bit immediate operand, which is an // 8-bit immediate rotated by an arbitrary number of bits, or an 8-bit // immediate splatted into multiple bytes of the word. @@ -131,6 +137,11 @@ let ParserMatchClass = t2_so_imm_neg_asmoperand; } +// t2_asr_imm - Match an immediate that has bit {5} set to 1 +def t2_asr_imm : ImmLeaf 0 && Imm < 32; +}], t2_asr_imm_XFORM>; + /// imm0_4095 predicate - True if the 32-bit immediate is in the range [0,4095]. def imm0_4095_asmoperand: ImmAsmOperand<0,4095> { let Name = "Imm0_4095"; } def imm0_4095 : Operand, ImmLeaf; 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, t2_asr_imm:$shft), imm1_32:$pos), + (t2SSAT imm1_32:$pos, GPRnopc:$a, t2_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, t2_asr_imm:$shft), imm0_31:$pos), + (t2USAT imm0_31:$pos, GPRnopc:$a, t2_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,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=armv6-eabi %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,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=armv6-eabi %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) Index: llvm/test/CodeGen/Thumb2/thumb2-ssat-with-shift.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/Thumb2/thumb2-ssat-with-shift.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=thumbv8.1m.main-arm-none-eabi -mattr=+mve.fp,+fp64 %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/Thumb2/thumb2-usat-with-shift.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/Thumb2/thumb2-usat-with-shift.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=thumbv8.1m.main-arm-none-eabi -mattr=+mve.fp,+fp64 %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)