Index: llvm/lib/Target/RISCV/RISCVInstrInfo.td =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -415,6 +415,11 @@ N->getValueType(0)); }]>; +def TrailingZeros : SDNodeXFormgetTargetConstant(N->getAPIntValue().countTrailingZeros(), + SDLoc(N), N->getValueType(0)); +}]>; + def XLenSubTrailingOnes : SDNodeXFormgetXLen(); uint64_t TrailingOnes = N->getAPIntValue().countTrailingOnes(); @@ -423,7 +428,13 @@ }]>; // Checks if this mask is a non-empty sequence of ones starting at the -// least significant bit with the remainder zero and exceeds simm12. +// most/least significant bit with the remainder zero and exceeds simm32/simm12. +def LeadingOnesMask : PatLeaf<(imm), [{ + if (!N->hasOneUse()) + return false; + return !isInt<32>(N->getSExtValue()) && isMask_64(~N->getSExtValue()); +}], TrailingZeros>; + def TrailingOnesMask : PatLeaf<(imm), [{ if (!N->hasOneUse()) return false; @@ -1134,7 +1145,9 @@ def : PatGprUimmLog2XLen; def : PatGprUimmLog2XLen; -// AND with trailing ones mask exceeding simm12. +// AND with leading/trailing ones mask exceeding simm32/simm12. +def : Pat<(i64 (and GPR:$rs, LeadingOnesMask:$mask)), + (SLLI (SRLI $rs, LeadingOnesMask:$mask), LeadingOnesMask:$mask)>; def : Pat<(XLenVT (and GPR:$rs, TrailingOnesMask:$mask)), (SRLI (SLLI $rs, TrailingOnesMask:$mask), TrailingOnesMask:$mask)>; Index: llvm/test/CodeGen/RISCV/and.ll =================================================================== --- llvm/test/CodeGen/RISCV/and.ll +++ llvm/test/CodeGen/RISCV/and.ll @@ -70,3 +70,156 @@ ret i64 %a } +; Test for handling of AND with constant. If this constant exceeds simm32 and +; also is a non-empty sequence of ones starting at the most significant bit +; with the remainder zero, we can replace it with SRLI + SLLI. + +define i32 @and32_0x7ffff000(i32 %x) { +; RV32I-LABEL: and32_0x7ffff000: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a1, 524287 +; RV32I-NEXT: and a0, a0, a1 +; RV32I-NEXT: ret +; +; RV64I-LABEL: and32_0x7ffff000: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 524287 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: ret + %a = and i32 %x, 2147479552 + ret i32 %a +} + +define i32 @and32_0xfffff000(i32 %x) { +; RV32I-LABEL: and32_0xfffff000: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a1, 1048575 +; RV32I-NEXT: and a0, a0, a1 +; RV32I-NEXT: ret +; +; RV64I-LABEL: and32_0xfffff000: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 256 +; RV64I-NEXT: addiw a1, a1, -1 +; RV64I-NEXT: slli a1, a1, 12 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: ret + %a = and i32 %x, -4096 + ret i32 %a +} + +define i32 @and32_0xfffffa00(i32 %x) { +; RV32I-LABEL: and32_0xfffffa00: +; RV32I: # %bb.0: +; RV32I-NEXT: andi a0, a0, -1536 +; RV32I-NEXT: ret +; +; RV64I-LABEL: and32_0xfffffa00: +; RV64I: # %bb.0: +; RV64I-NEXT: li a1, 1 +; RV64I-NEXT: slli a1, a1, 32 +; RV64I-NEXT: addi a1, a1, -1536 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: ret + %a = and i32 %x, -1536 + ret i32 %a +} + +define i64 @and64_0x7ffffffffffff000(i64 %x) { +; RV32I-LABEL: and64_0x7ffffffffffff000: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a2, 1048575 +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: slli a1, a1, 1 +; RV32I-NEXT: srli a1, a1, 1 +; RV32I-NEXT: ret +; +; RV64I-LABEL: and64_0x7ffffffffffff000: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 1048574 +; RV64I-NEXT: srli a1, a1, 1 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: ret + %a = and i64 %x, 9223372036854771712 + ret i64 %a +} + +define i64 @and64_0xfffffffffffff000(i64 %x) { +; RV32I-LABEL: and64_0xfffffffffffff000: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a2, 1048575 +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: ret +; +; RV64I-LABEL: and64_0xfffffffffffff000: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 1048575 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: ret + %a = and i64 %x, -4096 + ret i64 %a +} + +define i64 @and64_0xfffffffffffffa00(i64 %x) { +; RV32I-LABEL: and64_0xfffffffffffffa00: +; RV32I: # %bb.0: +; RV32I-NEXT: andi a0, a0, -1536 +; RV32I-NEXT: ret +; +; RV64I-LABEL: and64_0xfffffffffffffa00: +; RV64I: # %bb.0: +; RV64I-NEXT: andi a0, a0, -1536 +; RV64I-NEXT: ret + %a = and i64 %x, -1536 + ret i64 %a +} + +define i64 @and64_0xffffffff00000000(i64 %x) { +; RV32I-LABEL: and64_0xffffffff00000000: +; RV32I: # %bb.0: +; RV32I-NEXT: li a0, 0 +; RV32I-NEXT: ret +; +; RV64I-LABEL: and64_0xffffffff00000000: +; RV64I: # %bb.0: +; RV64I-NEXT: srli a0, a0, 32 +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: ret + %a = and i64 %x, -4294967296 + ret i64 %a +} + +define i64 @and64_0x7fffffff00000000(i64 %x) { +; RV32I-LABEL: and64_0x7fffffff00000000: +; RV32I: # %bb.0: +; RV32I-NEXT: slli a0, a1, 1 +; RV32I-NEXT: srli a1, a0, 1 +; RV32I-NEXT: li a0, 0 +; RV32I-NEXT: ret +; +; RV64I-LABEL: and64_0x7fffffff00000000: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 524288 +; RV64I-NEXT: addiw a1, a1, -1 +; RV64I-NEXT: slli a1, a1, 32 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: ret + %a = and i64 %x, 9223372032559808512 + ret i64 %a +} + +define i64 @and64_0xffffffff80000000(i64 %x) { +; RV32I-LABEL: and64_0xffffffff80000000: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a2, 524288 +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: ret +; +; RV64I-LABEL: and64_0xffffffff80000000: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 524288 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: ret + %a = and i64 %x, -2147483648 + ret i64 %a +} Index: llvm/test/CodeGen/RISCV/copysign-casts.ll =================================================================== --- llvm/test/CodeGen/RISCV/copysign-casts.ll +++ llvm/test/CodeGen/RISCV/copysign-casts.ll @@ -280,12 +280,11 @@ ; ; RV64I-LABEL: fold_demote_s_d: ; RV64I: # %bb.0: -; RV64I-NEXT: li a2, -1 -; RV64I-NEXT: slli a2, a2, 63 -; RV64I-NEXT: and a1, a1, a2 -; RV64I-NEXT: srli a1, a1, 32 ; RV64I-NEXT: slli a0, a0, 33 ; RV64I-NEXT: srli a0, a0, 33 +; RV64I-NEXT: srli a1, a1, 63 +; RV64I-NEXT: slli a1, a1, 63 +; RV64I-NEXT: srli a1, a1, 32 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: ret ; @@ -431,12 +430,11 @@ ; ; RV64I-LABEL: fold_demote_h_d: ; RV64I: # %bb.0: -; RV64I-NEXT: li a2, -1 -; RV64I-NEXT: slli a2, a2, 63 -; RV64I-NEXT: and a1, a1, a2 -; RV64I-NEXT: srli a1, a1, 48 ; RV64I-NEXT: slli a0, a0, 49 ; RV64I-NEXT: srli a0, a0, 49 +; RV64I-NEXT: srli a1, a1, 63 +; RV64I-NEXT: slli a1, a1, 63 +; RV64I-NEXT: srli a1, a1, 48 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: ret ; @@ -474,15 +472,14 @@ ; ; RV64IFD-LABEL: fold_demote_h_d: ; RV64IFD: # %bb.0: -; RV64IFD-NEXT: fmv.x.w a0, fa0 -; RV64IFD-NEXT: fmv.x.d a1, fa1 -; RV64IFD-NEXT: li a2, -1 -; RV64IFD-NEXT: slli a2, a2, 63 -; RV64IFD-NEXT: and a1, a1, a2 -; RV64IFD-NEXT: srli a1, a1, 48 -; RV64IFD-NEXT: slli a0, a0, 49 -; RV64IFD-NEXT: srli a0, a0, 49 -; RV64IFD-NEXT: or a0, a0, a1 +; RV64IFD-NEXT: fmv.x.d a0, fa1 +; RV64IFD-NEXT: fmv.x.w a1, fa0 +; RV64IFD-NEXT: slli a1, a1, 49 +; RV64IFD-NEXT: srli a1, a1, 49 +; RV64IFD-NEXT: srli a0, a0, 63 +; RV64IFD-NEXT: slli a0, a0, 63 +; RV64IFD-NEXT: srli a0, a0, 48 +; RV64IFD-NEXT: or a0, a1, a0 ; RV64IFD-NEXT: lui a1, 1048560 ; RV64IFD-NEXT: or a0, a0, a1 ; RV64IFD-NEXT: fmv.w.x fa0, a0 Index: llvm/test/CodeGen/RISCV/double-arith.ll =================================================================== --- llvm/test/CodeGen/RISCV/double-arith.ll +++ llvm/test/CodeGen/RISCV/double-arith.ll @@ -199,9 +199,8 @@ ; ; RV64I-LABEL: fsgnj_d: ; RV64I: # %bb.0: -; RV64I-NEXT: li a2, -1 -; RV64I-NEXT: slli a2, a2, 63 -; RV64I-NEXT: and a1, a1, a2 +; RV64I-NEXT: srli a1, a1, 63 +; RV64I-NEXT: slli a1, a1, 63 ; RV64I-NEXT: slli a0, a0, 1 ; RV64I-NEXT: srli a0, a0, 1 ; RV64I-NEXT: or a0, a0, a1 @@ -291,11 +290,10 @@ ; RV64I-LABEL: fsgnjn_d: ; RV64I: # %bb.0: ; RV64I-NEXT: not a1, a1 -; RV64I-NEXT: li a2, -1 -; RV64I-NEXT: slli a2, a2, 63 -; RV64I-NEXT: and a1, a1, a2 ; RV64I-NEXT: slli a0, a0, 1 ; RV64I-NEXT: srli a0, a0, 1 +; RV64I-NEXT: srli a1, a1, 63 +; RV64I-NEXT: slli a1, a1, 63 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: ret %1 = fsub double -0.0, %b Index: llvm/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll =================================================================== --- llvm/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll +++ llvm/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll @@ -113,11 +113,10 @@ ; RV64I-LABEL: fcopysign_fneg: ; RV64I: # %bb.0: ; RV64I-NEXT: not a1, a1 -; RV64I-NEXT: li a2, -1 -; RV64I-NEXT: slli a2, a2, 63 -; RV64I-NEXT: and a1, a1, a2 ; RV64I-NEXT: slli a0, a0, 1 ; RV64I-NEXT: srli a0, a0, 1 +; RV64I-NEXT: srli a1, a1, 63 +; RV64I-NEXT: slli a1, a1, 63 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: ret ; Index: llvm/test/CodeGen/RISCV/double-intrinsics.ll =================================================================== --- llvm/test/CodeGen/RISCV/double-intrinsics.ll +++ llvm/test/CodeGen/RISCV/double-intrinsics.ll @@ -735,9 +735,8 @@ ; ; RV64I-LABEL: copysign_f64: ; RV64I: # %bb.0: -; RV64I-NEXT: li a2, -1 -; RV64I-NEXT: slli a2, a2, 63 -; RV64I-NEXT: and a1, a1, a2 +; RV64I-NEXT: srli a1, a1, 63 +; RV64I-NEXT: slli a1, a1, 63 ; RV64I-NEXT: slli a0, a0, 1 ; RV64I-NEXT: srli a0, a0, 1 ; RV64I-NEXT: or a0, a0, a1 Index: llvm/test/CodeGen/RISCV/rv64zbp.ll =================================================================== --- llvm/test/CodeGen/RISCV/rv64zbp.ll +++ llvm/test/CodeGen/RISCV/rv64zbp.ll @@ -3279,9 +3279,8 @@ ; RV64I-LABEL: packu_i64: ; RV64I: # %bb.0: ; RV64I-NEXT: srli a0, a0, 32 -; RV64I-NEXT: li a2, -1 -; RV64I-NEXT: slli a2, a2, 32 -; RV64I-NEXT: and a1, a1, a2 +; RV64I-NEXT: srli a1, a1, 32 +; RV64I-NEXT: slli a1, a1, 32 ; RV64I-NEXT: or a0, a1, a0 ; RV64I-NEXT: ret ;