<div dir="ltr"><div><div>Thanks, Akira.<br></div>The first bitcast isn't necessary; I missed handling the case where the source type of the bitcast feeding the extract isn't a vector itself.<br></div>I'll add a check + test case and try again!<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Dec 10, 2015 at 1:07 AM, Akira Hatanaka <span dir="ltr"><<a href="mailto:ahatanak@gmail.com" target="_blank">ahatanak@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Sanjay,<div><br></div><div>I reverted this in r255227.</div><div><br></div><div>This causes an assert when the following IR is compiled with "opt -instcombine":</div><div>







<p><span>define internal double @foo1(<2 x double> %a) {</span></p>
<p><span>  %1 = bitcast <2 x double> %a to i128</span></p>
<p><span>  %2 = bitcast i128 %1 to <2 x i64></span></p>
<p><span>  %3 = extractelement <2 x i64> %2, i32 0</span></p>
<p><span>  %4 = bitcast i64 %3 to double</span></p>
<p><span>  ret double %4</span></p>
<p><span>}</span></p></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Dec 9, 2015 at 10:57 AM, Sanjay Patel 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: spatel<br>
Date: Wed Dec  9 12:57:16 2015<br>
New Revision: 255137<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=255137&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=255137&view=rev</a><br>
Log:<br>
[InstCombine] fold bitcasts around an extractelement (2nd try)<br>
<br>
This is a redo of r255124 (reverted at r255126) with an added check for a<br>
scalar destination type and an added test for the failure seen in Clang's<br>
test/CodeGen/vector.c. The extra test shows a different missing optimization.<br>
<br>
Original commit message:<br>
<br>
Example:<br>
  bitcast (extractelement (bitcast <2 x float> %X to <2 x i32>), 1) to float<br>
    ---><br>
  extractelement <2 x float> %X, i32 1<br>
<br>
This is part of fixing PR25543:<br>
<a href="https://llvm.org/bugs/show_bug.cgi?id=25543" rel="noreferrer" target="_blank">https://llvm.org/bugs/show_bug.cgi?id=25543</a><br>
<br>
The next step will be to generalize this fold:<br>
trunc ( lshr ( bitcast X) ) -> extractelement (X)<br>
<br>
Ie, I'm hoping to replace the existing transform of:<br>
bitcast ( trunc ( lshr ( bitcast X)))<br>
added by:<br>
<a href="http://reviews.llvm.org/rL112232" rel="noreferrer" target="_blank">http://reviews.llvm.org/rL112232</a><br>
<br>
with 2 less specific transforms to catch the case in the bug report.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D14879" rel="noreferrer" target="_blank">http://reviews.llvm.org/D14879</a><br>
<br>
<br>
Modified:<br>
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp<br>
    llvm/trunk/test/Transforms/InstCombine/bitcast.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=255137&r1=255136&r2=255137&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp?rev=255137&r1=255136&r2=255137&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp Wed Dec  9 12:57:16 2015<br>
@@ -1715,6 +1715,42 @@ static Value *optimizeIntegerToVectorIns<br>
   return Result;<br>
 }<br>
<br>
+/// Given a bitcasted vector fed into an extract element instruction and then<br>
+/// bitcasted again to a scalar type, eliminate at least one bitcast by changing<br>
+/// the vector type of the extractelement instruction.<br>
+/// Example:<br>
+///   bitcast (extractelement (bitcast <2 x float> %X to <2 x i32>), 1) to float<br>
+///    ---><br>
+///   extractelement <2 x float> %X, i32 1<br>
+static Instruction *foldBitCastExtElt(BitCastInst &BitCast, InstCombiner &IC,<br>
+                                      const DataLayout &DL) {<br>
+  Type *DestType = BitCast.getType();<br>
+  if (DestType->isVectorTy())<br>
+    return nullptr;<br>
+<br>
+  // TODO: Create and use a pattern matcher for ExtractElementInst.<br>
+  auto *ExtElt = dyn_cast<ExtractElementInst>(BitCast.getOperand(0));<br>
+  if (!ExtElt || !ExtElt->hasOneUse())<br>
+    return nullptr;<br>
+<br>
+  Value *InnerBitCast = nullptr;<br>
+  if (!match(ExtElt->getOperand(0), m_BitCast(m_Value(InnerBitCast))))<br>
+    return nullptr;<br>
+<br>
+  // If the element type of the vector doesn't match the result type,<br>
+  // bitcast it to a vector type that we can extract from.<br>
+  VectorType *VecType = cast<VectorType>(InnerBitCast->getType());<br>
+  if (VecType->getElementType() != DestType) {<br>
+    unsigned VecWidth = VecType->getPrimitiveSizeInBits();<br>
+    unsigned DestWidth = DestType->getPrimitiveSizeInBits();<br>
+    unsigned NumElts = VecWidth / DestWidth;<br>
+    VecType = VectorType::get(DestType, NumElts);<br>
+    InnerBitCast = IC.Builder->CreateBitCast(InnerBitCast, VecType, "bc");<br>
+  }<br>
+<br>
+  return ExtractElementInst::Create(InnerBitCast, ExtElt->getOperand(1));<br>
+}<br>
+<br>
 static Instruction *foldVecTruncToExtElt(Value *VecInput, Type *DestTy,<br>
                                          unsigned ShiftAmt, InstCombiner &IC,<br>
                                          const DataLayout &DL) {<br>
@@ -1886,6 +1922,9 @@ Instruction *InstCombiner::visitBitCast(<br>
     }<br>
   }<br>
<br>
+  if (Instruction *I = foldBitCastExtElt(CI, *this, DL))<br>
+    return I;<br>
+<br>
   if (SrcTy->isPointerTy())<br>
     return commonPointerCastTransforms(CI);<br>
   return commonCastTransforms(CI);<br>
<br>
Modified: llvm/trunk/test/Transforms/InstCombine/bitcast.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/bitcast.ll?rev=255137&r1=255136&r2=255137&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/bitcast.ll?rev=255137&r1=255136&r2=255137&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/InstCombine/bitcast.ll (original)<br>
+++ llvm/trunk/test/Transforms/InstCombine/bitcast.ll Wed Dec  9 12:57:16 2015<br>
@@ -64,7 +64,7 @@ define float @test3(<2 x float> %A, <2 x<br>
 ; CHECK-NEXT:  ret float %add<br>
 }<br>
<br>
-; TODO: Both bitcasts are unnecessary; change the extractelement.<br>
+; Both bitcasts are unnecessary; change the extractelement.<br>
<br>
 define float @bitcast_extelt1(<2 x float> %A) {<br>
   %bc1 = bitcast <2 x float> %A to <2 x i32><br>
@@ -73,13 +73,11 @@ define float @bitcast_extelt1(<2 x float<br>
   ret float %bc2<br>
<br>
 ; CHECK-LABEL: @bitcast_extelt1(<br>
-; CHECK-NEXT:  %bc1 = bitcast <2 x float> %A to <2 x i32><br>
-; CHECK-NEXT:  %ext = extractelement <2 x i32> %bc1, i32 0<br>
-; CHECK-NEXT:  %bc2 = bitcast i32 %ext to float<br>
+; CHECK-NEXT:  %bc2 = extractelement <2 x float> %A, i32 0<br>
 ; CHECK-NEXT:  ret float %bc2<br>
 }<br>
<br>
-; TODO: Second bitcast can be folded into the first.<br>
+; Second bitcast can be folded into the first.<br>
<br>
 define i64 @bitcast_extelt2(<4 x float> %A) {<br>
   %bc1 = bitcast <4 x float> %A to <2 x double><br>
@@ -88,12 +86,26 @@ define i64 @bitcast_extelt2(<4 x float><br>
   ret i64 %bc2<br>
<br>
 ; CHECK-LABEL: @bitcast_extelt2(<br>
-; CHECK-NEXT:  %bc1 = bitcast <4 x float> %A to <2 x double><br>
-; CHECK-NEXT:  %ext = extractelement <2 x double> %bc1, i32 1<br>
-; CHECK-NEXT:  %bc2 = bitcast double %ext to i64<br>
+; CHECK-NEXT:  %bc = bitcast <4 x float> %A to <2 x i64><br>
+; CHECK-NEXT:  %bc2 = extractelement <2 x i64> %bc, i32 1<br>
 ; CHECK-NEXT:  ret i64 %bc2<br>
 }<br>
<br>
+; TODO: This should return %A.<br>
+<br>
+define <2 x i32> @bitcast_extelt3(<2 x i32> %A) {<br>
+  %bc1 = bitcast <2 x i32> %A to <1 x i64><br>
+  %ext = extractelement <1 x i64> %bc1, i32 0<br>
+  %bc2 = bitcast i64 %ext to <2 x i32><br>
+  ret <2 x i32> %bc2<br>
+<br>
+; CHECK-LABEL: @bitcast_extelt3(<br>
+; CHECK-NEXT:  %bc1 = bitcast <2 x i32> %A to <1 x i64><br>
+; CHECK-NEXT:  %ext = extractelement <1 x i64> %bc1, i32 0<br>
+; CHECK-NEXT:  %bc2 = bitcast i64 %ext to <2 x i32><br>
+; CHECK-NEXT:  ret <2 x i32> %bc2<br>
+}<br>
+<br>
 define <2 x i32> @test4(i32 %A, i32 %B){<br>
   %tmp38 = zext i32 %A to i64<br>
   %tmp32 = zext i32 %B to i64<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">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>
</div></div></blockquote></div><br></div>