[llvm-commits] [llvm] r128732 - in /llvm/trunk: lib/Transforms/InstCombine/InstCombineCasts.cpp test/Transforms/InstCombine/sext.ll

Frits van Bommel fvbommel at gmail.com
Fri Apr 1 14:46:41 PDT 2011


On Fri, Apr 1, 2011 at 10:09 PM, Benjamin Kramer
<benny.kra at googlemail.com> wrote:
> +  // Transforming icmps with more than one use is not profitable.
> +  if (!ICI->hasOneUse())
> +    return 0;

Did you test this?
Intuitively, independent icmp + ashr could be more efficient than a
(sext (icmp)) with extra uses for the icmp. Then again, they may not
be since they introduce an extra use of 'x'.
Just a thought.

> +
>   if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
>     // (x <s 0) ? -1 : 0 -> ashr x, 31   -> all ones if signed
>     // (x >s -1) ? -1 : 0 -> ashr x, 31  -> all ones if not signed
> @@ -898,6 +902,52 @@
>         In = Builder->CreateNot(In, In->getName()+".not");
>       return ReplaceInstUsesWith(CI, In);
>     }
> +
> +    // If we know that only one bit of the LHS of the icmp can be set and we
> +    // have an equality comparison with zero or a power of 2, we can transform
> +    // the icmp and sext into bitwise/integer operations.
> +    if (ICI->isEquality() && (Op1C->isZero() || Op1C->getValue().isPowerOf2())){
> +      unsigned BitWidth = Op1C->getType()->getBitWidth();
> +      APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0);
> +      APInt TypeMask(APInt::getAllOnesValue(BitWidth));
> +      ComputeMaskedBits(Op0, TypeMask, KnownZero, KnownOne);
> +
> +      if ((~KnownZero).isPowerOf2()) {
> +        Value *In = ICI->getOperand(0);
> +
> +        if (!Op1C->isZero() == (Pred == ICmpInst::ICMP_NE)) {
> +          // sext ((x & 2^n) == 0)   -> (x >> n) - 1
> +          // sext ((x & 2^n) != 2^n) -> (x >> n) - 1

Did I miss where you checked whether the RHS of the and is equal to
the RHS of the icmp for the second case?
Or does this miscompile e.g. sext((x & 8) != 16)?
(You can optimize that to -1, of course)

> +          unsigned ShiftAmt = KnownZeroMask.countTrailingZeros();
> +          // Perform a right shift to place the desired bit in the LSB.
> +          if (ShiftAmt)
> +            In = Builder->CreateLShr(In,
> +                                     ConstantInt::get(In->getType(), ShiftAmt));
> +
> +          // At this point "In" is either 1 or 0. Subtract 1 to turn
> +          // {1, 0} -> {0, -1}.
> +          In = Builder->CreateAdd(In,
> +                                  ConstantInt::getAllOnesValue(In->getType()),
> +                                  "sext");
> +        } else {
> +          // sext ((x & 2^n) != 0)   -> (x << bitwidth-n) a>> bitwidth-1
> +          // sext ((x & 2^n) != 2^n) -> (x << bitwidth-n) a>> bitwidth-1

I think you meant '==' in the second case.
And this seems to have the same issue as above, miscompiling 'sext((x
& 8) == 16)' (which is 0).

> +          unsigned ShiftAmt = KnownZeroMask.countLeadingZeros();
> +          // Perform a left shift to place the desired bit in the MSB.
> +          if (ShiftAmt)
> +            In = Builder->CreateShl(In,
> +                                    ConstantInt::get(In->getType(), ShiftAmt));
> +
> +          // Distribute the bit over the whole bit width.
> +          In = Builder->CreateAShr(In, ConstantInt::get(In->getType(),
> +                                                        BitWidth - 1), "sext");
> +        }
> +
> +        if (CI.getType() == In->getType())
> +          return ReplaceInstUsesWith(CI, In);
> +        return CastInst::CreateIntegerCast(In, CI.getType(), true/*SExt*/);
> +      }
> +    }
>   }




More information about the llvm-commits mailing list