[llvm] r246997 - There is a trunc(lshr (zext A), Cst) optimization in InstCombineCasts that

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 9 13:21:32 PDT 2015


This patch wrongly transforms:
define i16 @f(i8 %V) {
  %conv = sext i8 %V to i32
  %shr.1.i = lshr i32 %conv, 1
  %conv.i = trunc i32 %shr.1.i to i16
  ret i16 %conv.i
}

into:

define i16 @f(i8 %V) {
  %shr.1.i = ashr i8 %V, 1
  %conv.i = zext i8 %shr.1.i to i16
  ret i16 %conv.i
}

If %V is 0x80, %conv.i should be 0xFFC0 but your transform will make
it 0x00C0.

This is the root cause of PR24763 and has been reverted in r247180.


On Tue, Sep 8, 2015 at 3:03 AM, Jakub Kuderski via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: kuhar
> Date: Tue Sep  8 05:03:17 2015
> New Revision: 246997
>
> URL: http://llvm.org/viewvc/llvm-project?rev=246997&view=rev
> Log:
> There is a trunc(lshr (zext A), Cst) optimization in InstCombineCasts that
> removes cast by performing the lshr on smaller types. However, currently
> there
> is no trunc(lshr (sext A), Cst) variant.
> This patch add such optimization by transforming trunc(lshr (sext A), Cst)
> to ashr A, Cst.
>
> Differential Revision: http://reviews.llvm.org/D12520
>
> Modified:
>     llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp
>     llvm/trunk/test/Transforms/InstCombine/cast.ll
>
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp?rev=246997&r1=246996&r2=246997&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp Tue Sep  8
> 05:03:17 2015
> @@ -499,6 +499,26 @@ Instruction *InstCombiner::visitTrunc(Tr
>      return CastInst::CreateIntegerCast(Shift, CI.getType(), false);
>    }
>
> +  // Transform trunc(lshr (sext A), Cst) to ashr A, Cst to eliminate type
> +  // conversion.
> +  // It works because bits coming from sign extension have the same value
> as
> +  // sign bit of the original value; performing ashr instead of lshr
> +  // generates bits of the same value as the sign bit.
> +  if (Src->hasOneUse() &&
> +      match(Src, m_LShr(m_SExt(m_Value(A)), m_ConstantInt(Cst))) &&
> +      cast<Instruction>(Src)->getOperand(0)->hasOneUse()) {
> +    const unsigned ASize = A->getType()->getPrimitiveSizeInBits();
> +    // This optimization can be only performed when zero bits generated by
> +    // the original lshr aren't pulled into the value after truncation,
> so we
> +    // can only shift by values smaller then the size of destination type
> (in
> +    // bits).
> +    if (Cst->getValue().ult(ASize)) {
> +      Value *Shift = Builder->CreateAShr(A, Cst->getZExtValue());
> +      Shift->takeName(Src);
> +      return CastInst::CreateIntegerCast(Shift, CI.getType(), false);
> +    }
> +  }
> +
>    // Transform "trunc (and X, cst)" -> "and (trunc X), cst" so long as
> the dest
>    // type isn't non-native.
>    if (Src->hasOneUse() && isa<IntegerType>(Src->getType()) &&
>
> Modified: llvm/trunk/test/Transforms/InstCombine/cast.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/cast.ll?rev=246997&r1=246996&r2=246997&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/InstCombine/cast.ll (original)
> +++ llvm/trunk/test/Transforms/InstCombine/cast.ll Tue Sep  8 05:03:17 2015
> @@ -1062,6 +1062,43 @@ define i8 @test85(i32 %a) {
>  ; CHECK: [[CST:%.*]] = trunc i32 [[SHR]] to i8
>  }
>
> +define i16 @test86(i16 %v) {
> +  %a = sext i16 %v to i32
> +  %s = ashr i32 %a, 4
> +  %t = trunc i32 %s to i16
> +  ret i16 %t
> +
> +; CHECK-LABEL: @test86(
> +; CHECK:  [[ASHR:%.*]] = ashr i16 %v, 4
> +; CHECK-NEXT: ret i16 [[ASHR]]
> +}
> +
> +define i16 @test87(i16 %v) {
> +  %c = sext i16 %v to i32
> +  %m = mul nsw i32 %c, 16
> +  %a = ashr i32 %m, 16
> +  %t = trunc i32 %a to i16
> +  ret i16 %t
> +
> +; CHECK-LABEL: @test87(
> +; CHECK:  [[ASHR:%.*]] = ashr i16 %v, 12
> +; CHECK-NEXT: ret i16 [[ASHR]]
> +}
> +
> +define i16 @test88(i16 %v) {
> +  %a = sext i16 %v to i32
> +  %s = ashr i32 %a, 18
> +  %t = trunc i32 %s to i16
> +  ret i16 %t
> +
> +; Do not optimize to ashr i16 (shift by 18)
> +; CHECK-LABEL: @test88(
> +; CHECK: [[SEXT:%.*]] = sext i16 %v to i32
> +; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[SEXT]], 18
> +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[ASHR]] to i16
> +; CHECK-NEXT: ret i16 [[TRUNC]]
> +}
> +
>  ; Overflow on a float to int or int to float conversion is undefined
> (PR21130).
>
>  define i8 @overflow_fptosi() {
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150909/0065f4cd/attachment.html>


More information about the llvm-commits mailing list