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 @@ -9369,11 +9369,13 @@ // shift amount. if (N->getOpcode() == ISD::SHL) { SDLoc DL(N); + SDNodeFlags Flags = N->getFlags(); SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(0)); SDValue NewOp1 = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, N->getOperand(1)); - SDValue NewWOp = DAG.getNode(ISD::SHL, DL, MVT::i64, NewOp0, NewOp1); + SDValue NewWOp = + DAG.getNode(ISD::SHL, DL, MVT::i64, NewOp0, NewOp1, Flags); SDValue NewRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, NewWOp, DAG.getValueType(MVT::i32)); Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, NewRes)); @@ -13025,11 +13027,17 @@ // What is the fewest number of bits we need to represent the negative number. unsigned MinSignedBits = ExpandedMask.getSignificantBits(); + APInt NewMask = ShrunkMask; + NewMask.setBitsFrom(31); + if (Opcode == ISD::AND && MinSignedBits == 64 && NewMask.isSignedIntN(12) && + ShrunkMask.isSignedIntN(32)) { + return UseMask(NewMask); + } // Try to make a 12 bit negative immediate. If that fails try to make a 32 // bit negative immediate unless the shrunk immediate already fits in 32 bits. // If we can't create a simm12, we shouldn't change opaque constants. - APInt NewMask = ShrunkMask; + NewMask = ShrunkMask; if (MinSignedBits <= 12) NewMask.setBitsFrom(11); else if (!C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.isSignedIntN(32)) diff --git a/llvm/test/CodeGen/RISCV/branch-on-zero.ll b/llvm/test/CodeGen/RISCV/branch-on-zero.ll --- a/llvm/test/CodeGen/RISCV/branch-on-zero.ll +++ b/llvm/test/CodeGen/RISCV/branch-on-zero.ll @@ -92,7 +92,7 @@ ; RV64-NEXT: .LBB2_2: # %for.body ; RV64-NEXT: # =>This Inner Loop Header: Depth=1 ; RV64-NEXT: andi a2, a0, 1 -; RV64-NEXT: srliw a0, a0, 1 +; RV64-NEXT: srli a0, a0, 1 ; RV64-NEXT: addw a1, a1, a2 ; RV64-NEXT: bnez a0, .LBB2_2 ; RV64-NEXT: .LBB2_3: # %for.end diff --git a/llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll b/llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll --- a/llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll +++ b/llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll @@ -192,3 +192,15 @@ %or = or i32 %and, 255 ret i32 %or } + +; https://alive2.llvm.org/ce/z/RizyWW +define i32 @shl_add_neg4(i32 noundef %x) { +; CHECK-LABEL: shl_add_neg4: +; CHECK: # %bb.0: +; CHECK-NEXT: slli a0, a0, 1 +; CHECK-NEXT: andi a0, a0, -4 +; CHECK-NEXT: ret + %y = shl nuw nsw i32 %x, 1 + %z = and i32 %y, 2147483644 + ret i32 %z +}