[llvm] r288584 - [InstCombine] change select type to eliminate bitcasts

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sat Dec 3 07:25:16 PST 2016


Author: spatel
Date: Sat Dec  3 09:25:16 2016
New Revision: 288584

URL: http://llvm.org/viewvc/llvm-project?rev=288584&view=rev
Log:
[InstCombine] change select type to eliminate bitcasts

This solves a secondary problem seen in PR6137:
https://llvm.org/bugs/show_bug.cgi?id=6137#c6

This is similar to the bitwise logic op fold added with:
https://reviews.llvm.org/rL287707

And like that patch, I'm artificially restricting the
transform from vector <-> scalar types until we're sure
that the backend can handle that. 

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp
    llvm/trunk/test/Transforms/InstCombine/bitcast.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp?rev=288584&r1=288583&r2=288584&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp Sat Dec  3 09:25:16 2016
@@ -1824,6 +1824,50 @@ static Instruction *foldBitCastBitwiseLo
   return nullptr;
 }
 
+/// Change the type of a select if we can eliminate a bitcast.
+static Instruction *foldBitCastSelect(BitCastInst &BitCast,
+                                      InstCombiner::BuilderTy &Builder) {
+  Value *Cond, *TVal, *FVal;
+  if (!match(BitCast.getOperand(0),
+             m_OneUse(m_Select(m_Value(Cond), m_Value(TVal), m_Value(FVal)))))
+    return nullptr;
+
+  // A vector select must maintain the same number of elements in its operands.
+  Type *CondTy = Cond->getType();
+  Type *DestTy = BitCast.getType();
+  if (CondTy->isVectorTy()) {
+    if (!DestTy->isVectorTy())
+      return nullptr;
+    if (DestTy->getVectorNumElements() != CondTy->getVectorNumElements())
+      return nullptr;
+  }
+
+  // FIXME: This transform is restricted from changing the select between
+  // scalars and vectors to avoid backend problems caused by creating
+  // potentially illegal operations. If a fix-up is added to handle that
+  // situation, we can remove this check.
+  if (DestTy->isVectorTy() != TVal->getType()->isVectorTy())
+    return nullptr;
+
+  auto *Sel = cast<Instruction>(BitCast.getOperand(0));
+  Value *X;
+  if (match(TVal, m_OneUse(m_BitCast(m_Value(X)))) && X->getType() == DestTy &&
+      !isa<Constant>(X)) {
+    // bitcast(select(Cond, bitcast(X), Y)) --> select'(Cond, X, bitcast(Y))
+    Value *CastedVal = Builder.CreateBitCast(FVal, DestTy);
+    return SelectInst::Create(Cond, X, CastedVal, "", nullptr, Sel);
+  }
+
+  if (match(FVal, m_OneUse(m_BitCast(m_Value(X)))) && X->getType() == DestTy &&
+      !isa<Constant>(X)) {
+    // bitcast(select(Cond, Y, bitcast(X))) --> select'(Cond, bitcast(Y), X)
+    Value *CastedVal = Builder.CreateBitCast(TVal, DestTy);
+    return SelectInst::Create(Cond, CastedVal, X, "", nullptr, Sel);
+  }
+
+  return nullptr;
+}
+
 /// Check if all users of CI are StoreInsts.
 static bool hasStoreUsersOnly(CastInst &CI) {
   for (User *U : CI.users()) {
@@ -2079,6 +2123,9 @@ Instruction *InstCombiner::visitBitCast(
   if (Instruction *I = foldBitCastBitwiseLogic(CI, *Builder))
     return I;
 
+  if (Instruction *I = foldBitCastSelect(CI, *Builder))
+    return I;
+
   if (SrcTy->isPointerTy())
     return commonPointerCastTransforms(CI);
   return commonCastTransforms(CI);

Modified: llvm/trunk/test/Transforms/InstCombine/bitcast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/bitcast.ll?rev=288584&r1=288583&r2=288584&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/bitcast.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/bitcast.ll Sat Dec  3 09:25:16 2016
@@ -134,15 +134,12 @@ define <4 x i32> @bitcast_xor_bitcast(<4
   ret <4 x i32> %bc2
 }
 
-; FIXME: Change the type of the vector select to eliminate 2 bitcasts.
 ; https://llvm.org/bugs/show_bug.cgi?id=6137#c6
 
 define <4 x float> @bitcast_vector_select(<4 x float> %x, <2 x i64> %y, <4 x i1> %cmp) {
 ; CHECK-LABEL: @bitcast_vector_select(
-; CHECK-NEXT:    [[T4:%.*]] = bitcast <4 x float> %x to <4 x i32>
-; CHECK-NEXT:    [[T5:%.*]] = bitcast <2 x i64> %y to <4 x i32>
-; CHECK-NEXT:    [[T6:%.*]] = select <4 x i1> %cmp, <4 x i32> [[T4]], <4 x i32> [[T5]]
-; CHECK-NEXT:    [[T7:%.*]] = bitcast <4 x i32> [[T6]] to <4 x float>
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i64> %y to <4 x float>
+; CHECK-NEXT:    [[T7:%.*]] = select <4 x i1> %cmp, <4 x float> %x, <4 x float> [[TMP1]]
 ; CHECK-NEXT:    ret <4 x float> [[T7]]
 ;
   %t4 = bitcast <4 x float> %x to <4 x i32>
@@ -152,10 +149,23 @@ define <4 x float> @bitcast_vector_selec
   ret <4 x float> %t7
 }
 
-; FIXME: Change the type of the scalar select to eliminate a bitcast.
+define float @bitcast_scalar_select_of_scalars(float %x, i32 %y, i1 %cmp) {
+; CHECK-LABEL: @bitcast_scalar_select_of_scalars(
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i32 %y to float
+; CHECK-NEXT:    [[T7:%.*]] = select i1 %cmp, float %x, float [[TMP1]]
+; CHECK-NEXT:    ret float [[T7]]
+;
+  %t4 = bitcast float %x to i32
+  %t6 = select i1 %cmp, i32 %t4, i32 %y
+  %t7 = bitcast i32 %t6 to float
+  ret float %t7
+}
 
-define float @bitcast_scalar_select(float %x, <4 x i8> %y, i1 %cmp) {
-; CHECK-LABEL: @bitcast_scalar_select(
+; FIXME: We should change the select operand types to scalars, but we need to make
+; sure the backend can reverse that transform if needed.
+
+define float @bitcast_scalar_select_type_mismatch1(float %x, <4 x i8> %y, i1 %cmp) {
+; CHECK-LABEL: @bitcast_scalar_select_type_mismatch1(
 ; CHECK-NEXT:    [[T4:%.*]] = bitcast float %x to <4 x i8>
 ; CHECK-NEXT:    [[T6:%.*]] = select i1 %cmp, <4 x i8> [[T4]], <4 x i8> %y
 ; CHECK-NEXT:    [[T7:%.*]] = bitcast <4 x i8> [[T6]] to float
@@ -167,14 +177,26 @@ define float @bitcast_scalar_select(floa
   ret float %t7
 }
 
-; FIXME: Change the type of the scalar select of vectors to eliminate 2 bitcasts.
+; FIXME: We should change the select operand types to vectors, but we need to make
+; sure the backend can reverse that transform if needed.
+
+define <4 x i8> @bitcast_scalar_select_type_mismatch2(<4 x i8> %x, float %y, i1 %cmp) {
+; CHECK-LABEL: @bitcast_scalar_select_type_mismatch2(
+; CHECK-NEXT:    [[T4:%.*]] = bitcast <4 x i8> %x to float
+; CHECK-NEXT:    [[T6:%.*]] = select i1 %cmp, float [[T4]], float %y
+; CHECK-NEXT:    [[T7:%.*]] = bitcast float [[T6]] to <4 x i8>
+; CHECK-NEXT:    ret <4 x i8> [[T7]]
+;
+  %t4 = bitcast <4 x i8> %x to float
+  %t6 = select i1 %cmp, float %t4, float %y
+  %t7 = bitcast float %t6 to <4 x i8>
+  ret <4 x i8> %t7
+}
 
 define <4 x float> @bitcast_scalar_select_of_vectors(<4 x float> %x, <2 x i64> %y, i1 %cmp) {
 ; CHECK-LABEL: @bitcast_scalar_select_of_vectors(
-; CHECK-NEXT:    [[T4:%.*]] = bitcast <4 x float> %x to <4 x i32>
-; CHECK-NEXT:    [[T5:%.*]] = bitcast <2 x i64> %y to <4 x i32>
-; CHECK-NEXT:    [[T6:%.*]] = select i1 %cmp, <4 x i32> [[T4]], <4 x i32> [[T5]]
-; CHECK-NEXT:    [[T7:%.*]] = bitcast <4 x i32> [[T6]] to <4 x float>
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i64> %y to <4 x float>
+; CHECK-NEXT:    [[T7:%.*]] = select i1 %cmp, <4 x float> %x, <4 x float> [[TMP1]]
 ; CHECK-NEXT:    ret <4 x float> [[T7]]
 ;
   %t4 = bitcast <4 x float> %x to <4 x i32>




More information about the llvm-commits mailing list