diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -1323,6 +1323,23 @@ return DAG.getNode(ISD::AND, DL, MVT::i64, NewFMV, DAG.getConstant(~SignBit, DL, MVT::i64)); } + case RISCVISD::GREVI: { + // Combine (GREVI (GREVI x, C2), C1) -> (GREVI x, C1|C2) when C2 fits + // entirely into the trailing zeros of C1. + SDLoc DL(N); + auto GREVSrc = N->getOperand(0); + uint64_t ShAmt1 = N->getConstantOperandVal(1); + if (GREVSrc->getOpcode() != RISCVISD::GREVI) + break; + uint64_t ShAmt2 = GREVSrc.getConstantOperandVal(1); + GREVSrc = GREVSrc->getOperand(0); + uint64_t TZ = countTrailingZeros(ShAmt1); + if (ShAmt2 != (ShAmt2 & maskTrailingOnes(TZ))) + break; + return DAG.getNode( + RISCVISD::GREVI, DL, N->getValueType(0), GREVSrc, + DAG.getTargetConstant(ShAmt1 | ShAmt2, DL, Subtarget.getXLenVT())); + } case ISD::OR: if (auto GREV = combineORToGREV(SDValue(N, 0), DCI.DAG, Subtarget)) return GREV; diff --git a/llvm/test/CodeGen/RISCV/rv32Zbp.ll b/llvm/test/CodeGen/RISCV/rv32Zbp.ll --- a/llvm/test/CodeGen/RISCV/rv32Zbp.ll +++ b/llvm/test/CodeGen/RISCV/rv32Zbp.ll @@ -498,7 +498,6 @@ ret i64 %or } -; FIXME: we should generate grevi 3 here define i32 @grev3_i32(i32 %a) nounwind { ; RV32I-LABEL: grev3_i32: ; RV32I: # %bb.0: @@ -524,14 +523,12 @@ ; ; RV32IB-LABEL: grev3_i32: ; RV32IB: # %bb.0: -; RV32IB-NEXT: rev.p a0, a0 -; RV32IB-NEXT: rev2.n a0, a0 +; RV32IB-NEXT: rev.n a0, a0 ; RV32IB-NEXT: ret ; ; RV32IBP-LABEL: grev3_i32: ; RV32IBP: # %bb.0: -; RV32IBP-NEXT: rev.p a0, a0 -; RV32IBP-NEXT: rev2.n a0, a0 +; RV32IBP-NEXT: rev.n a0, a0 ; RV32IBP-NEXT: ret %and1 = shl i32 %a, 1 %shl1 = and i32 %and1, -1431655766 @@ -546,7 +543,6 @@ ret i32 %or2 } -; FIXME: we should generate grevi 3 here define i64 @grev3_i64(i64 %a) nounwind { ; RV32I-LABEL: grev3_i64: ; RV32I: # %bb.0: @@ -582,18 +578,14 @@ ; ; RV32IB-LABEL: grev3_i64: ; RV32IB: # %bb.0: -; RV32IB-NEXT: rev.p a1, a1 -; RV32IB-NEXT: rev.p a0, a0 -; RV32IB-NEXT: rev2.n a0, a0 -; RV32IB-NEXT: rev2.n a1, a1 +; RV32IB-NEXT: rev.n a0, a0 +; RV32IB-NEXT: rev.n a1, a1 ; RV32IB-NEXT: ret ; ; RV32IBP-LABEL: grev3_i64: ; RV32IBP: # %bb.0: -; RV32IBP-NEXT: rev.p a1, a1 -; RV32IBP-NEXT: rev.p a0, a0 -; RV32IBP-NEXT: rev2.n a0, a0 -; RV32IBP-NEXT: rev2.n a1, a1 +; RV32IBP-NEXT: rev.n a0, a0 +; RV32IBP-NEXT: rev.n a1, a1 ; RV32IBP-NEXT: ret %and1 = shl i64 %a, 1 %shl1 = and i64 %and1, -6148914691236517206 @@ -677,7 +669,6 @@ ret i64 %or } -; FIXME: we should generate grevi 5 here define i32 @grev5_i32(i32 %a) nounwind { ; RV32I-LABEL: grev5_i32: ; RV32I: # %bb.0: @@ -703,14 +694,12 @@ ; ; RV32IB-LABEL: grev5_i32: ; RV32IB: # %bb.0: -; RV32IB-NEXT: rev.p a0, a0 -; RV32IB-NEXT: rev4.b a0, a0 +; RV32IB-NEXT: grevi a0, a0, 5 ; RV32IB-NEXT: ret ; ; RV32IBP-LABEL: grev5_i32: ; RV32IBP: # %bb.0: -; RV32IBP-NEXT: rev.p a0, a0 -; RV32IBP-NEXT: rev4.b a0, a0 +; RV32IBP-NEXT: grevi a0, a0, 5 ; RV32IBP-NEXT: ret %and1 = shl i32 %a, 1 %shl1 = and i32 %and1, -1431655766 @@ -725,7 +714,6 @@ ret i32 %or2 } -; FIXME: we should generate grevi 5 here define i64 @grev5_i64(i64 %a) nounwind { ; RV32I-LABEL: grev5_i64: ; RV32I: # %bb.0: @@ -761,18 +749,14 @@ ; ; RV32IB-LABEL: grev5_i64: ; RV32IB: # %bb.0: -; RV32IB-NEXT: rev.p a1, a1 -; RV32IB-NEXT: rev.p a0, a0 -; RV32IB-NEXT: rev4.b a0, a0 -; RV32IB-NEXT: rev4.b a1, a1 +; RV32IB-NEXT: grevi a0, a0, 5 +; RV32IB-NEXT: grevi a1, a1, 5 ; RV32IB-NEXT: ret ; ; RV32IBP-LABEL: grev5_i64: ; RV32IBP: # %bb.0: -; RV32IBP-NEXT: rev.p a1, a1 -; RV32IBP-NEXT: rev.p a0, a0 -; RV32IBP-NEXT: rev4.b a0, a0 -; RV32IBP-NEXT: rev4.b a1, a1 +; RV32IBP-NEXT: grevi a0, a0, 5 +; RV32IBP-NEXT: grevi a1, a1, 5 ; RV32IBP-NEXT: ret %and1 = shl i64 %a, 1 %shl1 = and i64 %and1, -6148914691236517206 @@ -788,7 +772,6 @@ ret i64 %or2 } -; FIXME: we should generate grevi 6 here define i32 @grev6_i32(i32 %a) nounwind { ; RV32I-LABEL: grev6_i32: ; RV32I: # %bb.0: @@ -814,14 +797,12 @@ ; ; RV32IB-LABEL: grev6_i32: ; RV32IB: # %bb.0: -; RV32IB-NEXT: rev2.n a0, a0 -; RV32IB-NEXT: rev4.b a0, a0 +; RV32IB-NEXT: rev2.b a0, a0 ; RV32IB-NEXT: ret ; ; RV32IBP-LABEL: grev6_i32: ; RV32IBP: # %bb.0: -; RV32IBP-NEXT: rev2.n a0, a0 -; RV32IBP-NEXT: rev4.b a0, a0 +; RV32IBP-NEXT: rev2.b a0, a0 ; RV32IBP-NEXT: ret %and1 = shl i32 %a, 2 %shl1 = and i32 %and1, -858993460 @@ -836,7 +817,6 @@ ret i32 %or2 } -; FIXME: we should generate grevi 6 here define i64 @grev6_i64(i64 %a) nounwind { ; RV32I-LABEL: grev6_i64: ; RV32I: # %bb.0: @@ -872,18 +852,14 @@ ; ; RV32IB-LABEL: grev6_i64: ; RV32IB: # %bb.0: -; RV32IB-NEXT: rev2.n a1, a1 -; RV32IB-NEXT: rev2.n a0, a0 -; RV32IB-NEXT: rev4.b a0, a0 -; RV32IB-NEXT: rev4.b a1, a1 +; RV32IB-NEXT: rev2.b a0, a0 +; RV32IB-NEXT: rev2.b a1, a1 ; RV32IB-NEXT: ret ; ; RV32IBP-LABEL: grev6_i64: ; RV32IBP: # %bb.0: -; RV32IBP-NEXT: rev2.n a1, a1 -; RV32IBP-NEXT: rev2.n a0, a0 -; RV32IBP-NEXT: rev4.b a0, a0 -; RV32IBP-NEXT: rev4.b a1, a1 +; RV32IBP-NEXT: rev2.b a0, a0 +; RV32IBP-NEXT: rev2.b a1, a1 ; RV32IBP-NEXT: ret %and1 = shl i64 %a, 2 %shl1 = and i64 %and1, -3689348814741910324 @@ -898,7 +874,6 @@ ret i64 %or2 } -; FIXME: we should generate grevi 7 here define i32 @grev7_i32(i32 %a) nounwind { ; RV32I-LABEL: grev7_i32: ; RV32I: # %bb.0: @@ -933,16 +908,12 @@ ; ; RV32IB-LABEL: grev7_i32: ; RV32IB: # %bb.0: -; RV32IB-NEXT: rev.p a0, a0 -; RV32IB-NEXT: rev2.n a0, a0 -; RV32IB-NEXT: rev4.b a0, a0 +; RV32IB-NEXT: rev.b a0, a0 ; RV32IB-NEXT: ret ; ; RV32IBP-LABEL: grev7_i32: ; RV32IBP: # %bb.0: -; RV32IBP-NEXT: rev.p a0, a0 -; RV32IBP-NEXT: rev2.n a0, a0 -; RV32IBP-NEXT: rev4.b a0, a0 +; RV32IBP-NEXT: rev.b a0, a0 ; RV32IBP-NEXT: ret %and1 = shl i32 %a, 1 %shl1 = and i32 %and1, -1431655766 @@ -962,7 +933,6 @@ ret i32 %or3 } -; FIXME: we should generate grevi 7 here define i64 @grev7_i64(i64 %a) nounwind { ; RV32I-LABEL: grev7_i64: ; RV32I: # %bb.0: @@ -1012,22 +982,14 @@ ; ; RV32IB-LABEL: grev7_i64: ; RV32IB: # %bb.0: -; RV32IB-NEXT: rev.p a0, a0 -; RV32IB-NEXT: rev.p a1, a1 -; RV32IB-NEXT: rev2.n a1, a1 -; RV32IB-NEXT: rev2.n a0, a0 -; RV32IB-NEXT: rev4.b a0, a0 -; RV32IB-NEXT: rev4.b a1, a1 +; RV32IB-NEXT: rev.b a0, a0 +; RV32IB-NEXT: rev.b a1, a1 ; RV32IB-NEXT: ret ; ; RV32IBP-LABEL: grev7_i64: ; RV32IBP: # %bb.0: -; RV32IBP-NEXT: rev.p a0, a0 -; RV32IBP-NEXT: rev.p a1, a1 -; RV32IBP-NEXT: rev2.n a1, a1 -; RV32IBP-NEXT: rev2.n a0, a0 -; RV32IBP-NEXT: rev4.b a0, a0 -; RV32IBP-NEXT: rev4.b a1, a1 +; RV32IBP-NEXT: rev.b a0, a0 +; RV32IBP-NEXT: rev.b a1, a1 ; RV32IBP-NEXT: ret %and1 = shl i64 %a, 1 %shl1 = and i64 %and1, -6148914691236517206 diff --git a/llvm/test/CodeGen/RISCV/rv64Zbp.ll b/llvm/test/CodeGen/RISCV/rv64Zbp.ll --- a/llvm/test/CodeGen/RISCV/rv64Zbp.ll +++ b/llvm/test/CodeGen/RISCV/rv64Zbp.ll @@ -571,7 +571,6 @@ ret i64 %or } -; FIXME: we should generate greviw 3 here define signext i32 @grev3_i32(i32 signext %a) nounwind { ; RV64I-LABEL: grev3_i32: ; RV64I: # %bb.0: @@ -600,14 +599,12 @@ ; ; RV64IB-LABEL: grev3_i32: ; RV64IB: # %bb.0: -; RV64IB-NEXT: greviw a0, a0, 1 -; RV64IB-NEXT: greviw a0, a0, 2 +; RV64IB-NEXT: greviw a0, a0, 3 ; RV64IB-NEXT: ret ; ; RV64IBP-LABEL: grev3_i32: ; RV64IBP: # %bb.0: -; RV64IBP-NEXT: greviw a0, a0, 1 -; RV64IBP-NEXT: greviw a0, a0, 2 +; RV64IBP-NEXT: greviw a0, a0, 3 ; RV64IBP-NEXT: ret %and1 = shl i32 %a, 1 %shl1 = and i32 %and1, -1431655766 @@ -622,7 +619,6 @@ ret i32 %or2 } -; FIXME: we should generate grevi 3 here define i64 @grev3_i64(i64 %a) nounwind { ; RV64I-LABEL: grev3_i64: ; RV64I: # %bb.0: @@ -672,14 +668,12 @@ ; ; RV64IB-LABEL: grev3_i64: ; RV64IB: # %bb.0: -; RV64IB-NEXT: rev.p a0, a0 -; RV64IB-NEXT: rev2.n a0, a0 +; RV64IB-NEXT: rev.n a0, a0 ; RV64IB-NEXT: ret ; ; RV64IBP-LABEL: grev3_i64: ; RV64IBP: # %bb.0: -; RV64IBP-NEXT: rev.p a0, a0 -; RV64IBP-NEXT: rev2.n a0, a0 +; RV64IBP-NEXT: rev.n a0, a0 ; RV64IBP-NEXT: ret %and1 = shl i64 %a, 1 %shl1 = and i64 %and1, -6148914691236517206 @@ -771,7 +765,6 @@ ret i64 %or } -; FIXME: we should generate greviw 5 here define signext i32 @grev5_i32(i32 signext %a) nounwind { ; RV64I-LABEL: grev5_i32: ; RV64I: # %bb.0: @@ -800,14 +793,12 @@ ; ; RV64IB-LABEL: grev5_i32: ; RV64IB: # %bb.0: -; RV64IB-NEXT: greviw a0, a0, 1 -; RV64IB-NEXT: greviw a0, a0, 4 +; RV64IB-NEXT: greviw a0, a0, 5 ; RV64IB-NEXT: ret ; ; RV64IBP-LABEL: grev5_i32: ; RV64IBP: # %bb.0: -; RV64IBP-NEXT: greviw a0, a0, 1 -; RV64IBP-NEXT: greviw a0, a0, 4 +; RV64IBP-NEXT: greviw a0, a0, 5 ; RV64IBP-NEXT: ret %and1 = shl i32 %a, 1 %shl1 = and i32 %and1, -1431655766 @@ -822,7 +813,6 @@ ret i32 %or2 } -; FIXME: we should generate grevi 5 here define i64 @grev5_i64(i64 %a) nounwind { ; RV64I-LABEL: grev5_i64: ; RV64I: # %bb.0: @@ -872,14 +862,12 @@ ; ; RV64IB-LABEL: grev5_i64: ; RV64IB: # %bb.0: -; RV64IB-NEXT: rev.p a0, a0 -; RV64IB-NEXT: rev4.b a0, a0 +; RV64IB-NEXT: grevi a0, a0, 5 ; RV64IB-NEXT: ret ; ; RV64IBP-LABEL: grev5_i64: ; RV64IBP: # %bb.0: -; RV64IBP-NEXT: rev.p a0, a0 -; RV64IBP-NEXT: rev4.b a0, a0 +; RV64IBP-NEXT: grevi a0, a0, 5 ; RV64IBP-NEXT: ret %and1 = shl i64 %a, 1 %shl1 = and i64 %and1, -6148914691236517206 @@ -895,7 +883,6 @@ ret i64 %or2 } -; FIXME: we should generate greviw 6 here define signext i32 @grev6_i32(i32 signext %a) nounwind { ; RV64I-LABEL: grev6_i32: ; RV64I: # %bb.0: @@ -924,14 +911,12 @@ ; ; RV64IB-LABEL: grev6_i32: ; RV64IB: # %bb.0: -; RV64IB-NEXT: greviw a0, a0, 2 -; RV64IB-NEXT: greviw a0, a0, 4 +; RV64IB-NEXT: greviw a0, a0, 6 ; RV64IB-NEXT: ret ; ; RV64IBP-LABEL: grev6_i32: ; RV64IBP: # %bb.0: -; RV64IBP-NEXT: greviw a0, a0, 2 -; RV64IBP-NEXT: greviw a0, a0, 4 +; RV64IBP-NEXT: greviw a0, a0, 6 ; RV64IBP-NEXT: ret %and1 = shl i32 %a, 2 %shl1 = and i32 %and1, -858993460 @@ -946,7 +931,6 @@ ret i32 %or2 } -; FIXME: we should generate grevi 6 here define i64 @grev6_i64(i64 %a) nounwind { ; RV64I-LABEL: grev6_i64: ; RV64I: # %bb.0: @@ -996,14 +980,12 @@ ; ; RV64IB-LABEL: grev6_i64: ; RV64IB: # %bb.0: -; RV64IB-NEXT: rev2.n a0, a0 -; RV64IB-NEXT: rev4.b a0, a0 +; RV64IB-NEXT: rev2.b a0, a0 ; RV64IB-NEXT: ret ; ; RV64IBP-LABEL: grev6_i64: ; RV64IBP: # %bb.0: -; RV64IBP-NEXT: rev2.n a0, a0 -; RV64IBP-NEXT: rev4.b a0, a0 +; RV64IBP-NEXT: rev2.b a0, a0 ; RV64IBP-NEXT: ret %and1 = shl i64 %a, 2 %shl1 = and i64 %and1, -3689348814741910324 @@ -1018,7 +1000,6 @@ ret i64 %or2 } -; FIXME: we should generate greviw 7 here define signext i32 @grev7_i32(i32 signext %a) nounwind { ; RV64I-LABEL: grev7_i32: ; RV64I: # %bb.0: @@ -1056,16 +1037,12 @@ ; ; RV64IB-LABEL: grev7_i32: ; RV64IB: # %bb.0: -; RV64IB-NEXT: greviw a0, a0, 1 -; RV64IB-NEXT: greviw a0, a0, 2 -; RV64IB-NEXT: greviw a0, a0, 4 +; RV64IB-NEXT: greviw a0, a0, 7 ; RV64IB-NEXT: ret ; ; RV64IBP-LABEL: grev7_i32: ; RV64IBP: # %bb.0: -; RV64IBP-NEXT: greviw a0, a0, 1 -; RV64IBP-NEXT: greviw a0, a0, 2 -; RV64IBP-NEXT: greviw a0, a0, 4 +; RV64IBP-NEXT: greviw a0, a0, 7 ; RV64IBP-NEXT: ret %and1 = shl i32 %a, 1 %shl1 = and i32 %and1, -1431655766 @@ -1085,7 +1062,6 @@ ret i32 %or3 } -; FIXME: we should generate grevi 7 here define i64 @grev7_i64(i64 %a) nounwind { ; RV64I-LABEL: grev7_i64: ; RV64I: # %bb.0: @@ -1156,16 +1132,12 @@ ; ; RV64IB-LABEL: grev7_i64: ; RV64IB: # %bb.0: -; RV64IB-NEXT: rev.p a0, a0 -; RV64IB-NEXT: rev2.n a0, a0 -; RV64IB-NEXT: rev4.b a0, a0 +; RV64IB-NEXT: rev.b a0, a0 ; RV64IB-NEXT: ret ; ; RV64IBP-LABEL: grev7_i64: ; RV64IBP: # %bb.0: -; RV64IBP-NEXT: rev.p a0, a0 -; RV64IBP-NEXT: rev2.n a0, a0 -; RV64IBP-NEXT: rev4.b a0, a0 +; RV64IBP-NEXT: rev.b a0, a0 ; RV64IBP-NEXT: ret %and1 = shl i64 %a, 1 %shl1 = and i64 %and1, -6148914691236517206