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

Arnaud A. de Grandmaison via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 9 14:49:18 PDT 2015


+CC llvm-commits

 

From: Arnaud A. de Grandmaison [mailto:arnaud.degrandmaison at arm.com] 
Sent: 09 September 2015 23:37
To: 'David Majnemer'
Cc: Jakub Kuderski
Subject: RE: [llvm] r246997 - There is a trunc(lshr (zext A), Cst) optimization in InstCombineCasts that

 

The whole point of the patch is that we know which bits are actually sign bits. I think the line

+      return CastInst::CreateIntegerCast(Shift, CI.getType(), false);
should instead be

    return CastInst::CreateIntegerCast(Shift, CI.getType(), true);

because we otherwise loose the sign info.This is also what the comment describing the transformation says we want to do.

 

I missed that when reviewing the patch. The attached patch fix the issue (and adds David’s testcase).

 

Does that look reasonable to you David ?

 

Cheers,

Arnaud

 

 

From: llvm-commits [mailto:llvm-commits-bounces at lists.llvm.org] On Behalf Of David Majnemer via llvm-commits
Sent: 09 September 2015 22:22
To: Jakub Kuderski
Cc: llvm-commits
Subject: Re: [llvm] r246997 - There is a trunc(lshr (zext A), Cst) optimization in InstCombineCasts that

 

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 <http://llvm.org/viewvc/llvm-project?rev=246997&view=rev> &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 <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp?rev=246997&r1=246996&r2=246997&view=diff> &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 <http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/cast.ll?rev=246997&r1=246996&r2=246997&view=diff> &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/895d59d7/attachment.html>


More information about the llvm-commits mailing list