diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td index 38f36cb239535..6a94a5615e1c7 100644 --- a/llvm/lib/Target/ARM/ARMInstrMVE.td +++ b/llvm/lib/Target/ARM/ARMInstrMVE.td @@ -2568,6 +2568,13 @@ multiclass vqabsneg_pattern; + // InstCombine canonicalizes the saturating negate in the expression above + // to ssub.sat(0, r). + def : Pat<(VTI.Vec (vselect + (VTI.Pred (ARMvcmpz (VTI.Vec MQPR:$reg), ARMCCgt)), + (VTI.Vec MQPR:$reg), + (VTI.Vec (ssubsat (VTI.Vec zero_vec), (VTI.Vec MQPR:$reg))))), + (VTI.Vec (vqabs_instruction (VTI.Vec MQPR:$reg)))>; // Similarly, this tree represents vqneg, i.e. the following vectorized expression: // r == INT_MIN ? INT_MAX : -r def : Pat<(VTI.Vec (vselect @@ -2575,6 +2582,8 @@ multiclass vqabsneg_pattern; + def : Pat<(VTI.Vec (ssubsat (VTI.Vec zero_vec), (VTI.Vec MQPR:$reg))), + (VTI.Vec (vqneg_instruction (VTI.Vec MQPR:$reg)))>; } } diff --git a/llvm/test/CodeGen/Thumb2/vqabs.ll b/llvm/test/CodeGen/Thumb2/vqabs.ll index f8f4b65a1f7dc..832d85b1095c4 100644 --- a/llvm/test/CodeGen/Thumb2/vqabs.ll +++ b/llvm/test/CodeGen/Thumb2/vqabs.ll @@ -52,10 +52,7 @@ entry: define arm_aapcs_vfpcc <16 x i8> @vqabs_sat_test16(<16 x i8> %A) { ; CHECK-LABEL: vqabs_sat_test16: ; CHECK: @ %bb.0: @ %entry -; CHECK-NEXT: vmov.i32 q1, #0x0 -; CHECK-NEXT: vcmp.s8 gt, q0, zr -; CHECK-NEXT: vqsub.s8 q1, q1, q0 -; CHECK-NEXT: vpsel q0, q0, q1 +; CHECK-NEXT: vqabs.s8 q0, q0 ; CHECK-NEXT: bx lr entry: %0 = icmp sgt <16 x i8> %A, zeroinitializer @@ -67,10 +64,7 @@ entry: define arm_aapcs_vfpcc <8 x i16> @vqabs_sat_test8(<8 x i16> %A) { ; CHECK-LABEL: vqabs_sat_test8: ; CHECK: @ %bb.0: @ %entry -; CHECK-NEXT: vmov.i32 q1, #0x0 -; CHECK-NEXT: vcmp.s16 gt, q0, zr -; CHECK-NEXT: vqsub.s16 q1, q1, q0 -; CHECK-NEXT: vpsel q0, q0, q1 +; CHECK-NEXT: vqabs.s16 q0, q0 ; CHECK-NEXT: bx lr entry: %0 = icmp sgt <8 x i16> %A, zeroinitializer @@ -82,10 +76,7 @@ entry: define arm_aapcs_vfpcc <4 x i32> @vqabs_sat_test4(<4 x i32> %A) { ; CHECK-LABEL: vqabs_sat_test4: ; CHECK: @ %bb.0: @ %entry -; CHECK-NEXT: vmov.i32 q1, #0x0 -; CHECK-NEXT: vcmp.s32 gt, q0, zr -; CHECK-NEXT: vqsub.s32 q1, q1, q0 -; CHECK-NEXT: vpsel q0, q0, q1 +; CHECK-NEXT: vqabs.s32 q0, q0 ; CHECK-NEXT: bx lr entry: %0 = icmp sgt <4 x i32> %A, zeroinitializer diff --git a/llvm/test/CodeGen/Thumb2/vqneg.ll b/llvm/test/CodeGen/Thumb2/vqneg.ll index 4f357d81a5fc5..3a7c227bf4d22 100644 --- a/llvm/test/CodeGen/Thumb2/vqneg.ll +++ b/llvm/test/CodeGen/Thumb2/vqneg.ll @@ -46,8 +46,7 @@ entry: define arm_aapcs_vfpcc <16 x i8> @vqneg_sat_test16(<16 x i8> %A) { ; CHECK-LABEL: vqneg_sat_test16: ; CHECK: @ %bb.0: @ %entry -; CHECK-NEXT: vmov.i32 q1, #0x0 -; CHECK-NEXT: vqsub.s8 q0, q1, q0 +; CHECK-NEXT: vqneg.s8 q0, q0 ; CHECK-NEXT: bx lr entry: %0 = tail call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> zeroinitializer, <16 x i8> %A) @@ -57,8 +56,7 @@ entry: define arm_aapcs_vfpcc <8 x i16> @vqneg_sat_test8(<8 x i16> %A) { ; CHECK-LABEL: vqneg_sat_test8: ; CHECK: @ %bb.0: @ %entry -; CHECK-NEXT: vmov.i32 q1, #0x0 -; CHECK-NEXT: vqsub.s16 q0, q1, q0 +; CHECK-NEXT: vqneg.s16 q0, q0 ; CHECK-NEXT: bx lr entry: %0 = tail call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> zeroinitializer, <8 x i16> %A) @@ -68,8 +66,7 @@ entry: define arm_aapcs_vfpcc <4 x i32> @vqneg_sat_test4(<4 x i32> %A) { ; CHECK-LABEL: vqneg_sat_test4: ; CHECK: @ %bb.0: @ %entry -; CHECK-NEXT: vmov.i32 q1, #0x0 -; CHECK-NEXT: vqsub.s32 q0, q1, q0 +; CHECK-NEXT: vqneg.s32 q0, q0 ; CHECK-NEXT: bx lr entry: %0 = tail call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> zeroinitializer, <4 x i32> %A)