This is an archive of the discontinued LLVM Phabricator instance.

[Reassociate] Teach ConvertShiftToMul to preserve nsw flag if the shift amount is not bitwidth - 1.
ClosedPublic

Authored by craig.topper on Jun 4 2020, 12:28 PM.

Details

Summary

Multiply and shl have different signed overflow behavior in
some cases. But it looks like we should be ok as long as the
shift amount is less than bitwidth - 1.

Alive2: http://volta.cs.utah.edu:8080/z/MM4WZP

Diff Detail

Event Timeline

craig.topper created this revision.Jun 4 2020, 12:28 PM
Herald added a project: Restricted Project. · View Herald TranscriptJun 4 2020, 12:28 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
This revision is now accepted and ready to land.Jun 4 2020, 12:52 PM

Grepping a bit, there's this:

const SCEV *ScalarEvolution::createSCEV(Value *V) {
<...>

    case Instruction::Shl:
      // Turn shift left of a constant amount into a multiply.
      if (ConstantInt *SA = dyn_cast<ConstantInt>(BO->RHS)) {
        uint32_t BitWidth = cast<IntegerType>(SA->getType())->getBitWidth();

        // If the shift count is not less than the bitwidth, the result of
        // the shift is undefined. Don't try to analyze it, because the
        // resolution chosen here may differ from the resolution chosen in
        // other parts of the compiler.
        if (SA->getValue().uge(BitWidth))
          break;

        // It is currently not resolved how to interpret NSW for left
        // shift by BitWidth - 1, so we avoid applying flags in that
        // case. Remove this check (or this comment) once the situation
        // is resolved. See
        // http://lists.llvm.org/pipermail/llvm-dev/2015-April/084195.html
        // and http://reviews.llvm.org/D8890 .
        auto Flags = SCEV::FlagAnyWrap;
        if (BO->Op && SA->getValue().ult(BitWidth - 1))
          Flags = getNoWrapFlagsFromUB(BO->Op);

        Constant *X = ConstantInt::get(
            getContext(), APInt::getOneBitSet(BitWidth, SA->getZExtValue()));
        return getMulExpr(getSCEV(BO->LHS), getSCEV(X), Flags);
      }
      break;

But apparently langref was fixed in rL286785, so we're good and i'll post SCEV patch.

This revision was automatically updated to reflect the committed changes.