Index: llvm/lib/Target/AArch64/AArch64ISelLowering.h =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -496,6 +496,10 @@ return VT.getSizeInBits() >= 64; // vector 'bic' } + bool convertSelectOfConstantsToMath(EVT VT) const override { + return true; + } + bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd( SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y, unsigned OldShiftOpcode, unsigned NewShiftOpcode, Index: llvm/test/CodeGen/AArch64/select_const.ll =================================================================== --- llvm/test/CodeGen/AArch64/select_const.ll +++ llvm/test/CodeGen/AArch64/select_const.ll @@ -127,9 +127,8 @@ define i32 @select_Cplus1_C(i1 %cond) { ; CHECK-LABEL: select_Cplus1_C: ; CHECK: // %bb.0: -; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #41 -; CHECK-NEXT: cinc w0, w8, ne +; CHECK-NEXT: and w8, w0, #0x1 +; CHECK-NEXT: add w0, w8, #41 // =41 ; CHECK-NEXT: ret %sel = select i1 %cond, i32 42, i32 41 ret i32 %sel @@ -138,9 +137,7 @@ define i32 @select_Cplus1_C_zeroext(i1 zeroext %cond) { ; CHECK-LABEL: select_Cplus1_C_zeroext: ; CHECK: // %bb.0: -; CHECK-NEXT: cmp w0, #0 // =0 -; CHECK-NEXT: mov w8, #41 -; CHECK-NEXT: cinc w0, w8, ne +; CHECK-NEXT: add w0, w0, #41 // =41 ; CHECK-NEXT: ret %sel = select i1 %cond, i32 42, i32 41 ret i32 %sel @@ -149,9 +146,8 @@ define i32 @select_Cplus1_C_signext(i1 signext %cond) { ; CHECK-LABEL: select_Cplus1_C_signext: ; CHECK: // %bb.0: -; CHECK-NEXT: tst w0, #0x1 ; CHECK-NEXT: mov w8, #41 -; CHECK-NEXT: cinc w0, w8, ne +; CHECK-NEXT: sub w0, w8, w0 ; CHECK-NEXT: ret %sel = select i1 %cond, i32 42, i32 41 ret i32 %sel @@ -162,9 +158,9 @@ define i32 @select_C_Cplus1(i1 %cond) { ; CHECK-LABEL: select_C_Cplus1: ; CHECK: // %bb.0: -; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #41 -; CHECK-NEXT: cinc w0, w8, eq +; CHECK-NEXT: and w8, w0, #0x1 +; CHECK-NEXT: mov w9, #42 +; CHECK-NEXT: sub w0, w9, w8 ; CHECK-NEXT: ret %sel = select i1 %cond, i32 41, i32 42 ret i32 %sel @@ -173,9 +169,8 @@ define i32 @select_C_Cplus1_zeroext(i1 zeroext %cond) { ; CHECK-LABEL: select_C_Cplus1_zeroext: ; CHECK: // %bb.0: -; CHECK-NEXT: cmp w0, #0 // =0 -; CHECK-NEXT: mov w8, #41 -; CHECK-NEXT: cinc w0, w8, eq +; CHECK-NEXT: mov w8, #42 +; CHECK-NEXT: sub w0, w8, w0 ; CHECK-NEXT: ret %sel = select i1 %cond, i32 41, i32 42 ret i32 %sel @@ -184,9 +179,7 @@ define i32 @select_C_Cplus1_signext(i1 signext %cond) { ; CHECK-LABEL: select_C_Cplus1_signext: ; CHECK: // %bb.0: -; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #41 -; CHECK-NEXT: cinc w0, w8, eq +; CHECK-NEXT: add w0, w0, #42 // =42 ; CHECK-NEXT: ret %sel = select i1 %cond, i32 41, i32 42 ret i32 %sel @@ -361,9 +354,9 @@ define i8 @sel_constants_urem_constant(i1 %cond) { ; CHECK-LABEL: sel_constants_urem_constant: ; CHECK: // %bb.0: -; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #2 -; CHECK-NEXT: cinc w0, w8, eq +; CHECK-NEXT: and w8, w0, #0x1 +; CHECK-NEXT: mov w9, #3 +; CHECK-NEXT: sub w0, w9, w8 ; CHECK-NEXT: ret %sel = select i1 %cond, i8 -4, i8 23 %bo = urem i8 %sel, 5 @@ -386,9 +379,9 @@ define i8 @sel_constants_and_constant(i1 %cond) { ; CHECK-LABEL: sel_constants_and_constant: ; CHECK: // %bb.0: -; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #4 -; CHECK-NEXT: cinc w0, w8, eq +; CHECK-NEXT: and w8, w0, #0x1 +; CHECK-NEXT: mov w9, #5 +; CHECK-NEXT: sub w0, w9, w8 ; CHECK-NEXT: ret %sel = select i1 %cond, i8 -4, i8 23 %bo = and i8 %sel, 5 @@ -437,9 +430,10 @@ define i8 @shl_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: shl_constant_sel_constants: ; CHECK: // %bb.0: -; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #2 -; CHECK-NEXT: cinc x8, x8, eq +; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-NEXT: and x8, x0, #0x1 +; CHECK-NEXT: mov w9, #3 +; CHECK-NEXT: sub x8, x9, x8 ; CHECK-NEXT: mov w9, #1 ; CHECK-NEXT: lsl w0, w9, w8 ; CHECK-NEXT: ret @@ -463,9 +457,10 @@ define i8 @lshr_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: lshr_constant_sel_constants: ; CHECK: // %bb.0: -; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #2 -; CHECK-NEXT: cinc x8, x8, eq +; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-NEXT: and x8, x0, #0x1 +; CHECK-NEXT: mov w9, #3 +; CHECK-NEXT: sub x8, x9, x8 ; CHECK-NEXT: mov w9, #64 ; CHECK-NEXT: lsr w0, w9, w8 ; CHECK-NEXT: ret @@ -488,9 +483,10 @@ define i8 @ashr_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: ashr_constant_sel_constants: ; CHECK: // %bb.0: -; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #2 -; CHECK-NEXT: cinc x8, x8, eq +; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-NEXT: and x8, x0, #0x1 +; CHECK-NEXT: mov w9, #3 +; CHECK-NEXT: sub x8, x9, x8 ; CHECK-NEXT: mov w9, #-128 ; CHECK-NEXT: asr w0, w9, w8 ; CHECK-NEXT: ret Index: llvm/test/CodeGen/AArch64/selectcc-to-shiftand.ll =================================================================== --- llvm/test/CodeGen/AArch64/selectcc-to-shiftand.ll +++ llvm/test/CodeGen/AArch64/selectcc-to-shiftand.ll @@ -71,8 +71,9 @@ define i32 @pos_sel_special_constant(i32 %a) { ; CHECK-LABEL: pos_sel_special_constant: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #512 -; CHECK-NEXT: bic w0, w8, w0, lsr #22 +; CHECK-NEXT: mvn w8, w0 +; CHECK-NEXT: lsr w8, w8, #22 +; CHECK-NEXT: and w0, w8, #0x200 ; CHECK-NEXT: ret %tmp.1 = icmp sgt i32 %a, -1 %retval = select i1 %tmp.1, i32 512, i32 0 @@ -132,9 +133,8 @@ define i16 @sel_shift_bool_i16(i1 %t) { ; CHECK-LABEL: sel_shift_bool_i16: ; CHECK: // %bb.0: -; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #128 -; CHECK-NEXT: csel w0, w8, wzr, ne +; CHECK-NEXT: and w8, w0, #0x1 +; CHECK-NEXT: lsl w0, w8, #7 ; CHECK-NEXT: ret %shl = select i1 %t, i16 128, i16 0 ret i16 %shl @@ -143,9 +143,8 @@ define i32 @sel_shift_bool_i32(i1 %t) { ; CHECK-LABEL: sel_shift_bool_i32: ; CHECK: // %bb.0: -; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #64 -; CHECK-NEXT: csel w0, w8, wzr, ne +; CHECK-NEXT: and w8, w0, #0x1 +; CHECK-NEXT: lsl w0, w8, #6 ; CHECK-NEXT: ret %shl = select i1 %t, i32 64, i32 0 ret i32 %shl @@ -154,9 +153,9 @@ define i64 @sel_shift_bool_i64(i1 %t) { ; CHECK-LABEL: sel_shift_bool_i64: ; CHECK: // %bb.0: -; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #65536 -; CHECK-NEXT: csel x0, x8, xzr, ne +; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-NEXT: and x8, x0, #0x1 +; CHECK-NEXT: lsl x0, x8, #16 ; CHECK-NEXT: ret %shl = select i1 %t, i64 65536, i64 0 ret i64 %shl @@ -165,10 +164,9 @@ define <16 x i8> @sel_shift_bool_v16i8(<16 x i1> %t) { ; CHECK-LABEL: sel_shift_bool_v16i8: ; CHECK: // %bb.0: -; CHECK-NEXT: shl v0.16b, v0.16b, #7 -; CHECK-NEXT: sshr v0.16b, v0.16b, #7 -; CHECK-NEXT: movi v1.16b, #128 +; CHECK-NEXT: movi v1.16b, #1 ; CHECK-NEXT: and v0.16b, v0.16b, v1.16b +; CHECK-NEXT: shl v0.16b, v0.16b, #7 ; CHECK-NEXT: ret %shl = select <16 x i1> %t, <16 x i8> , <16 x i8> zeroinitializer ret <16 x i8> %shl @@ -177,11 +175,9 @@ define <8 x i16> @sel_shift_bool_v8i16(<8 x i1> %t) { ; CHECK-LABEL: sel_shift_bool_v8i16: ; CHECK: // %bb.0: -; CHECK-NEXT: ushll v0.8h, v0.8b, #0 -; CHECK-NEXT: shl v0.8h, v0.8h, #15 -; CHECK-NEXT: sshr v0.8h, v0.8h, #15 -; CHECK-NEXT: movi v1.8h, #128 -; CHECK-NEXT: and v0.16b, v0.16b, v1.16b +; CHECK-NEXT: movi v1.8b, #1 +; CHECK-NEXT: and v0.8b, v0.8b, v1.8b +; CHECK-NEXT: ushll v0.8h, v0.8b, #7 ; CHECK-NEXT: ret %shl= select <8 x i1> %t, <8 x i16> , <8 x i16> zeroinitializer ret <8 x i16> %shl @@ -190,11 +186,9 @@ define <4 x i32> @sel_shift_bool_v4i32(<4 x i1> %t) { ; CHECK-LABEL: sel_shift_bool_v4i32: ; CHECK: // %bb.0: -; CHECK-NEXT: ushll v0.4s, v0.4h, #0 -; CHECK-NEXT: shl v0.4s, v0.4s, #31 -; CHECK-NEXT: sshr v0.4s, v0.4s, #31 -; CHECK-NEXT: movi v1.4s, #64 -; CHECK-NEXT: and v0.16b, v0.16b, v1.16b +; CHECK-NEXT: movi v1.4h, #1 +; CHECK-NEXT: and v0.8b, v0.8b, v1.8b +; CHECK-NEXT: ushll v0.4s, v0.4h, #6 ; CHECK-NEXT: ret %shl = select <4 x i1> %t, <4 x i32> , <4 x i32> zeroinitializer ret <4 x i32> %shl @@ -203,12 +197,9 @@ define <2 x i64> @sel_shift_bool_v2i64(<2 x i1> %t) { ; CHECK-LABEL: sel_shift_bool_v2i64: ; CHECK: // %bb.0: -; CHECK-NEXT: ushll v0.2d, v0.2s, #0 -; CHECK-NEXT: mov w8, #65536 -; CHECK-NEXT: shl v0.2d, v0.2d, #63 -; CHECK-NEXT: sshr v0.2d, v0.2d, #63 -; CHECK-NEXT: dup v1.2d, x8 -; CHECK-NEXT: and v0.16b, v0.16b, v1.16b +; CHECK-NEXT: movi v1.2s, #1 +; CHECK-NEXT: and v0.8b, v0.8b, v1.8b +; CHECK-NEXT: ushll v0.2d, v0.2s, #16 ; CHECK-NEXT: ret %shl = select <2 x i1> %t, <2 x i64> , <2 x i64> zeroinitializer ret <2 x i64> %shl Index: llvm/test/CodeGen/AArch64/signbit-shift.ll =================================================================== --- llvm/test/CodeGen/AArch64/signbit-shift.ll +++ llvm/test/CodeGen/AArch64/signbit-shift.ll @@ -43,9 +43,8 @@ define i32 @sel_ifpos_tval_bigger(i32 %x) { ; CHECK-LABEL: sel_ifpos_tval_bigger: ; CHECK: // %bb.0: -; CHECK-NEXT: cmp w0, #0 // =0 -; CHECK-NEXT: mov w8, #41 -; CHECK-NEXT: cinc w0, w8, ge +; CHECK-NEXT: asr w8, w0, #31 +; CHECK-NEXT: add w0, w8, #42 // =42 ; CHECK-NEXT: ret %c = icmp sgt i32 %x, -1 %r = select i1 %c, i32 42, i32 41 @@ -92,9 +91,8 @@ define i32 @sel_ifpos_fval_bigger(i32 %x) { ; CHECK-LABEL: sel_ifpos_fval_bigger: ; CHECK: // %bb.0: -; CHECK-NEXT: cmp w0, #0 // =0 -; CHECK-NEXT: mov w8, #41 -; CHECK-NEXT: cinc w0, w8, lt +; CHECK-NEXT: lsr w8, w0, #31 +; CHECK-NEXT: add w0, w8, #41 // =41 ; CHECK-NEXT: ret %c = icmp sgt i32 %x, -1 %r = select i1 %c, i32 41, i32 42 @@ -128,9 +126,8 @@ define i32 @sel_ifneg_tval_bigger(i32 %x) { ; CHECK-LABEL: sel_ifneg_tval_bigger: ; CHECK: // %bb.0: -; CHECK-NEXT: cmp w0, #0 // =0 -; CHECK-NEXT: mov w8, #41 -; CHECK-NEXT: cinc w0, w8, lt +; CHECK-NEXT: lsr w8, w0, #31 +; CHECK-NEXT: add w0, w8, #41 // =41 ; CHECK-NEXT: ret %c = icmp slt i32 %x, 0 %r = select i1 %c, i32 42, i32 41 @@ -162,9 +159,8 @@ define i32 @sel_ifneg_fval_bigger(i32 %x) { ; CHECK-LABEL: sel_ifneg_fval_bigger: ; CHECK: // %bb.0: -; CHECK-NEXT: cmp w0, #0 // =0 -; CHECK-NEXT: mov w8, #41 -; CHECK-NEXT: cinc w0, w8, ge +; CHECK-NEXT: asr w8, w0, #31 +; CHECK-NEXT: add w0, w8, #42 // =42 ; CHECK-NEXT: ret %c = icmp slt i32 %x, 0 %r = select i1 %c, i32 41, i32 42 Index: llvm/test/CodeGen/AArch64/vselect-constants.ll =================================================================== --- llvm/test/CodeGen/AArch64/vselect-constants.ll +++ llvm/test/CodeGen/AArch64/vselect-constants.ll @@ -42,13 +42,10 @@ ; CHECK-LABEL: sel_Cplus1_or_C_vec: ; CHECK: // %bb.0: ; CHECK-NEXT: adrp x8, .LCPI2_0 -; CHECK-NEXT: adrp x9, .LCPI2_1 ; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI2_0] -; CHECK-NEXT: ldr q2, [x9, :lo12:.LCPI2_1] -; CHECK-NEXT: ushll v0.4s, v0.4h, #0 -; CHECK-NEXT: shl v0.4s, v0.4s, #31 -; CHECK-NEXT: sshr v0.4s, v0.4s, #31 -; CHECK-NEXT: bsl v0.16b, v2.16b, v1.16b +; CHECK-NEXT: movi v2.4h, #1 +; CHECK-NEXT: and v0.8b, v0.8b, v2.8b +; CHECK-NEXT: uaddw v0.4s, v1.4s, v0.4h ; CHECK-NEXT: ret %add = select <4 x i1> %cond, <4 x i32> , <4 x i32> ret <4 x i32> %add @@ -58,11 +55,9 @@ ; CHECK-LABEL: cmp_sel_Cplus1_or_C_vec: ; CHECK: // %bb.0: ; CHECK-NEXT: adrp x8, .LCPI3_0 -; CHECK-NEXT: adrp x9, .LCPI3_1 ; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI3_0] -; CHECK-NEXT: ldr q3, [x9, :lo12:.LCPI3_1] ; CHECK-NEXT: cmeq v0.4s, v0.4s, v1.4s -; CHECK-NEXT: bsl v0.16b, v3.16b, v2.16b +; CHECK-NEXT: sub v0.4s, v2.4s, v0.4s ; CHECK-NEXT: ret %cond = icmp eq <4 x i32> %x, %y %add = select <4 x i1> %cond, <4 x i32> , <4 x i32> @@ -73,13 +68,11 @@ ; CHECK-LABEL: sel_Cminus1_or_C_vec: ; CHECK: // %bb.0: ; CHECK-NEXT: adrp x8, .LCPI4_0 -; CHECK-NEXT: adrp x9, .LCPI4_1 ; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI4_0] -; CHECK-NEXT: ldr q2, [x9, :lo12:.LCPI4_1] ; CHECK-NEXT: ushll v0.4s, v0.4h, #0 ; CHECK-NEXT: shl v0.4s, v0.4s, #31 -; CHECK-NEXT: sshr v0.4s, v0.4s, #31 -; CHECK-NEXT: bsl v0.16b, v2.16b, v1.16b +; CHECK-NEXT: ssra v1.4s, v0.4s, #31 +; CHECK-NEXT: mov v0.16b, v1.16b ; CHECK-NEXT: ret %add = select <4 x i1> %cond, <4 x i32> , <4 x i32> ret <4 x i32> %add @@ -89,11 +82,9 @@ ; CHECK-LABEL: cmp_sel_Cminus1_or_C_vec: ; CHECK: // %bb.0: ; CHECK-NEXT: adrp x8, .LCPI5_0 -; CHECK-NEXT: adrp x9, .LCPI5_1 ; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI5_0] -; CHECK-NEXT: ldr q3, [x9, :lo12:.LCPI5_1] ; CHECK-NEXT: cmeq v0.4s, v0.4s, v1.4s -; CHECK-NEXT: bsl v0.16b, v3.16b, v2.16b +; CHECK-NEXT: add v0.4s, v0.4s, v2.4s ; CHECK-NEXT: ret %cond = icmp eq <4 x i32> %x, %y %add = select <4 x i1> %cond, <4 x i32> , <4 x i32> @@ -124,9 +115,10 @@ define <4 x i32> @sel_0_or_minus1_vec(<4 x i1> %cond) { ; CHECK-LABEL: sel_0_or_minus1_vec: ; CHECK: // %bb.0: -; CHECK-NEXT: ushll v0.4s, v0.4h, #0 -; CHECK-NEXT: shl v0.4s, v0.4s, #31 -; CHECK-NEXT: cmge v0.4s, v0.4s, #0 +; CHECK-NEXT: movi v1.4h, #1 +; CHECK-NEXT: and v0.8b, v0.8b, v1.8b +; CHECK-NEXT: movi v1.2d, #0xffffffffffffffff +; CHECK-NEXT: uaddw v0.4s, v1.4s, v0.4h ; CHECK-NEXT: ret %add = select <4 x i1> %cond, <4 x i32> , <4 x i32> ret <4 x i32> %add @@ -146,11 +138,9 @@ define <4 x i32> @sel_1_or_0_vec(<4 x i1> %cond) { ; CHECK-LABEL: sel_1_or_0_vec: ; CHECK: // %bb.0: +; CHECK-NEXT: movi v1.4h, #1 +; CHECK-NEXT: and v0.8b, v0.8b, v1.8b ; CHECK-NEXT: ushll v0.4s, v0.4h, #0 -; CHECK-NEXT: shl v0.4s, v0.4s, #31 -; CHECK-NEXT: sshr v0.4s, v0.4s, #31 -; CHECK-NEXT: movi v1.4s, #1 -; CHECK-NEXT: and v0.16b, v0.16b, v1.16b ; CHECK-NEXT: ret %add = select <4 x i1> %cond, <4 x i32> , <4 x i32> ret <4 x i32> %add @@ -171,9 +161,9 @@ define <4 x i32> @sel_0_or_1_vec(<4 x i1> %cond) { ; CHECK-LABEL: sel_0_or_1_vec: ; CHECK: // %bb.0: +; CHECK-NEXT: movi v1.4h, #1 +; CHECK-NEXT: eor v0.8b, v0.8b, v1.8b ; CHECK-NEXT: ushll v0.4s, v0.4h, #0 -; CHECK-NEXT: shl v0.4s, v0.4s, #31 -; CHECK-NEXT: cmge v0.4s, v0.4s, #0 ; CHECK-NEXT: movi v1.4s, #1 ; CHECK-NEXT: and v0.16b, v0.16b, v1.16b ; CHECK-NEXT: ret @@ -185,8 +175,9 @@ ; CHECK-LABEL: cmp_sel_0_or_1_vec: ; CHECK: // %bb.0: ; CHECK-NEXT: cmeq v0.4s, v0.4s, v1.4s +; CHECK-NEXT: mvn v0.16b, v0.16b ; CHECK-NEXT: movi v1.4s, #1 -; CHECK-NEXT: bic v0.16b, v1.16b, v0.16b +; CHECK-NEXT: and v0.16b, v0.16b, v1.16b ; CHECK-NEXT: ret %cond = icmp eq <4 x i32> %x, %y %add = select <4 x i1> %cond, <4 x i32> , <4 x i32>