Index: llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -344,32 +344,33 @@ // Check that it is a SROIW (Shift Right Ones Immediate i32 on RV64). // We first check that it is the right node tree: // -// (OR (SHL RS1, VC2), VC1) +// (OR (SRL RS1, VC2), VC1) // // and then we check that VC1, the mask used to fill with ones, is compatible // with VC2, the shamt: // -// VC1 == maskLeadingOnes(VC2) - +// VC2 < 32 +// VC1 == maskTrailingZeros(32 - VC2) +// bool RISCVDAGToDAGISel::SelectSROIW(SDValue N, SDValue &RS1, SDValue &Shamt) { - if (N.getOpcode() == ISD::OR && Subtarget->getXLenVT() == MVT::i64) { - SDValue Or = N; - if (Or.getOperand(0).getOpcode() == ISD::SRL) { - SDValue Srl = Or.getOperand(0); - if (isa(Srl.getOperand(1)) && - isa(Or.getOperand(1))) { - uint32_t VC1 = Or.getConstantOperandVal(1); - uint32_t VC2 = Srl.getConstantOperandVal(1); - if (VC1 == maskLeadingOnes(VC2)) { - RS1 = Srl.getOperand(0); - Shamt = CurDAG->getTargetConstant(VC2, SDLoc(N), - Srl.getOperand(1).getValueType()); - return true; - } - } - } - } - return false; + assert(Subtarget->is64Bit() && "SROIW should only be matched on RV64"); + if (N.getOpcode() != ISD::OR || !isa(N.getOperand(1))) + return false; + + SDValue Srl = N.getOperand(0); + if (Srl.getOpcode() != ISD::SRL || !isa(Srl.getOperand(1))) + return false; + + uint64_t VC1 = N.getConstantOperandVal(1); + uint64_t VC2 = Srl.getConstantOperandVal(1); + + if (VC2 >= 32 || VC1 != maskTrailingZeros(32 - VC2)) + return false; + + RS1 = Srl.getOperand(0); + Shamt = CurDAG->getTargetConstant(VC2, SDLoc(N), + Srl.getOperand(1).getValueType()); + return true; } // Check that it is a RORIW (i32 Right Rotate Immediate on RV64). Index: llvm/test/CodeGen/RISCV/rv64Zbb.ll =================================================================== --- llvm/test/CodeGen/RISCV/rv64Zbb.ll +++ llvm/test/CodeGen/RISCV/rv64Zbb.ll @@ -166,7 +166,6 @@ ; This is similar to the type legalized version of sroiw but the mask is 0 in ; the upper bits instead of 1 so the result is not sign extended. Make sure we ; don't match it to sroiw. -; FIXME: We're matching it to sroiw. define i64 @sroiw_bug(i64 %a) nounwind { ; RV64I-LABEL: sroiw_bug: ; RV64I: # %bb.0: @@ -178,12 +177,18 @@ ; ; RV64IB-LABEL: sroiw_bug: ; RV64IB: # %bb.0: -; RV64IB-NEXT: sroiw a0, a0, 1 +; RV64IB-NEXT: srli a0, a0, 1 +; RV64IB-NEXT: addi a1, zero, 1 +; RV64IB-NEXT: slli a1, a1, 31 +; RV64IB-NEXT: or a0, a0, a1 ; RV64IB-NEXT: ret ; ; RV64IBB-LABEL: sroiw_bug: ; RV64IBB: # %bb.0: -; RV64IBB-NEXT: sroiw a0, a0, 1 +; RV64IBB-NEXT: srli a0, a0, 1 +; RV64IBB-NEXT: addi a1, zero, 1 +; RV64IBB-NEXT: slli a1, a1, 31 +; RV64IBB-NEXT: or a0, a0, a1 ; RV64IBB-NEXT: ret %neg = lshr i64 %a, 1 %neg12 = or i64 %neg, 2147483648