diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3385,16 +3385,19 @@ Known.Zero.setBitsFrom(1); break; } - case ISD::SHL: + case ISD::SHL: { Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); - Known = KnownBits::shl(Known, Known2); + SDNodeFlags Flags = Op.getNode()->getFlags(); + Known = KnownBits::shl(Known, Known2, Flags.hasNoUnsignedWrap(), + Flags.hasNoSignedWrap()); // Minimum shift low bits are known zero. if (const APInt *ShMinAmt = getValidMinimumShiftAmountConstant(Op, DemandedElts)) Known.Zero.setLowBits(ShMinAmt->getZExtValue()); break; + } case ISD::SRL: Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1763,10 +1763,10 @@ Depth + 1)) return true; assert(!Known.hasConflict() && "Bits known to be one AND zero?"); - Known.Zero <<= ShAmt; - Known.One <<= ShAmt; - // low bits known zero. - Known.Zero.setLowBits(ShAmt); + SDNodeFlags Flags = Op.getNode()->getFlags(); + Known = + KnownBits::shl(Known, KnownBits::makeConstant(APInt(BitWidth, ShAmt)), + Flags.hasNoUnsignedWrap(), Flags.hasNoSignedWrap()); // Attempt to avoid multi-use ops if we don't need anything from them. if (!InDemandedMask.isAllOnes() || !DemandedElts.isAllOnes()) { 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,18 @@ %or = or i32 %and, 255 ret i32 %or } + + +define i32 @test_shl_nuw__nsw_is_safe(i32 %x) { +; CHECK-LABEL: test_shl_nuw__nsw_is_safe: +; CHECK: # %bb.0: +; CHECK-NEXT: li a0, 0 +; CHECK-NEXT: ret + %1 = or i32 %x, -83886080 + %2 = icmp eq i32 %1, -83886079 + %3 = shl nuw i32 %1, 2 + %4 = select i1 %2, i32 -335544316, i32 %3 + %5 = mul i32 %4, %1 + %6 = mul i32 %5, %3 + ret i32 %6 +}