<div dir="ltr">This patch wrongly transforms:<div><div>define i16 @f(i8 %V) {</div><div>  %conv = sext i8 %V to i32</div><div>  %shr.1.i = lshr i32 %conv, 1</div><div>  %conv.i = trunc i32 %shr.1.i to i16</div><div>  ret i16 %conv.i</div><div>}</div></div><div><br></div><div>into:</div><div><br></div><div><div>define i16 @f(i8 %V) {</div><div>  %shr.1.i = ashr i8 %V, 1</div><div>  %conv.i = zext i8 %shr.1.i to i16</div><div>  ret i16 %conv.i</div><div>}</div></div><div><br></div><div>If %V is 0x80, %conv.i should be 0xFFC0 but your transform will make it 0x00C0.</div><div><br></div><div>This is the root cause of PR24763 and has been reverted in r247180.</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Sep 8, 2015 at 3:03 AM, Jakub Kuderski via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: kuhar<br>
Date: Tue Sep  8 05:03:17 2015<br>
New Revision: 246997<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=246997&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=246997&view=rev</a><br>
Log:<br>
There is a trunc(lshr (zext A), Cst) optimization in InstCombineCasts that<br>
removes cast by performing the lshr on smaller types. However, currently there<br>
is no trunc(lshr (sext A), Cst) variant.<br>
This patch add such optimization by transforming trunc(lshr (sext A), Cst)<br>
to ashr A, Cst.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D12520" rel="noreferrer" target="_blank">http://reviews.llvm.org/D12520</a><br>
<br>
Modified:<br>
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp<br>
    llvm/trunk/test/Transforms/InstCombine/cast.ll<br>
<br>
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp?rev=246997&r1=246996&r2=246997&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp?rev=246997&r1=246996&r2=246997&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp Tue Sep  8 05:03:17 2015<br>
@@ -499,6 +499,26 @@ Instruction *InstCombiner::visitTrunc(Tr<br>
     return CastInst::CreateIntegerCast(Shift, CI.getType(), false);<br>
   }<br>
<br>
+  // Transform trunc(lshr (sext A), Cst) to ashr A, Cst to eliminate type<br>
+  // conversion.<br>
+  // It works because bits coming from sign extension have the same value as<br>
+  // sign bit of the original value; performing ashr instead of lshr<br>
+  // generates bits of the same value as the sign bit.<br>
+  if (Src->hasOneUse() &&<br>
+      match(Src, m_LShr(m_SExt(m_Value(A)), m_ConstantInt(Cst))) &&<br>
+      cast<Instruction>(Src)->getOperand(0)->hasOneUse()) {<br>
+    const unsigned ASize = A->getType()->getPrimitiveSizeInBits();<br>
+    // This optimization can be only performed when zero bits generated by<br>
+    // the original lshr aren't pulled into the value after truncation, so we<br>
+    // can only shift by values smaller then the size of destination type (in<br>
+    // bits).<br>
+    if (Cst->getValue().ult(ASize)) {<br>
+      Value *Shift = Builder->CreateAShr(A, Cst->getZExtValue());<br>
+      Shift->takeName(Src);<br>
+      return CastInst::CreateIntegerCast(Shift, CI.getType(), false);<br>
+    }<br>
+  }<br>
+<br>
   // Transform "trunc (and X, cst)" -> "and (trunc X), cst" so long as the dest<br>
   // type isn't non-native.<br>
   if (Src->hasOneUse() && isa<IntegerType>(Src->getType()) &&<br>
<br>
Modified: llvm/trunk/test/Transforms/InstCombine/cast.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/cast.ll?rev=246997&r1=246996&r2=246997&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/cast.ll?rev=246997&r1=246996&r2=246997&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/InstCombine/cast.ll (original)<br>
+++ llvm/trunk/test/Transforms/InstCombine/cast.ll Tue Sep  8 05:03:17 2015<br>
@@ -1062,6 +1062,43 @@ define i8 @test85(i32 %a) {<br>
 ; CHECK: [[CST:%.*]] = trunc i32 [[SHR]] to i8<br>
 }<br>
<br>
+define i16 @test86(i16 %v) {<br>
+  %a = sext i16 %v to i32<br>
+  %s = ashr i32 %a, 4<br>
+  %t = trunc i32 %s to i16<br>
+  ret i16 %t<br>
+<br>
+; CHECK-LABEL: @test86(<br>
+; CHECK:  [[ASHR:%.*]] = ashr i16 %v, 4<br>
+; CHECK-NEXT: ret i16 [[ASHR]]<br>
+}<br>
+<br>
+define i16 @test87(i16 %v) {<br>
+  %c = sext i16 %v to i32<br>
+  %m = mul nsw i32 %c, 16<br>
+  %a = ashr i32 %m, 16<br>
+  %t = trunc i32 %a to i16<br>
+  ret i16 %t<br>
+<br>
+; CHECK-LABEL: @test87(<br>
+; CHECK:  [[ASHR:%.*]] = ashr i16 %v, 12<br>
+; CHECK-NEXT: ret i16 [[ASHR]]<br>
+}<br>
+<br>
+define i16 @test88(i16 %v) {<br>
+  %a = sext i16 %v to i32<br>
+  %s = ashr i32 %a, 18<br>
+  %t = trunc i32 %s to i16<br>
+  ret i16 %t<br>
+<br>
+; Do not optimize to ashr i16 (shift by 18)<br>
+; CHECK-LABEL: @test88(<br>
+; CHECK: [[SEXT:%.*]] = sext i16 %v to i32<br>
+; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[SEXT]], 18<br>
+; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[ASHR]] to i16<br>
+; CHECK-NEXT: ret i16 [[TRUNC]]<br>
+}<br>
+<br>
 ; Overflow on a float to int or int to float conversion is undefined (PR21130).<br>
<br>
 define i8 @overflow_fptosi() {<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>