[PATCH] D26641: [InstCombine] change bitwise logic type to eliminate bitcasts

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 14 15:27:41 PST 2016


spatel created this revision.
spatel added reviewers: efriedma, majnemer.
spatel added a subscriber: llvm-commits.
Herald added a subscriber: mcrosier.

In PR27925:
https://llvm.org/bugs/show_bug.cgi?id=27925

...we proposed adding this fold to eliminate a bitcast. In https://reviews.llvm.org/D20774, there was some concern about changing the type of a bitwise op as well as creating bitcasts that might not be free for a target. However, if we're strictly eliminating an instruction (by limiting this to one-use ops), then we should be able to do this in InstCombine.

I purposely chose vector+scalar types in a couple of the tests to show the possibility of changing the logic op from a scalar to vector or vice-versa. But again, I think we're safe because we can assume that the source and destination types are DataLayout-legal because InstCombine shouldn't be creating strange types. Ie, I would typically only expect this pattern to emerge for vector-vector bitcasts like in the PR27925 test.


https://reviews.llvm.org/D26641

Files:
  lib/Transforms/InstCombine/InstCombineCasts.cpp
  test/Transforms/InstCombine/bitcast.ll


Index: test/Transforms/InstCombine/bitcast.ll
===================================================================
--- test/Transforms/InstCombine/bitcast.ll
+++ test/Transforms/InstCombine/bitcast.ll
@@ -74,10 +74,8 @@
 
 define <4 x i32> @bitcasts_and_bitcast(<4 x i32> %a, <8 x i16> %b) {
 ; CHECK-LABEL: @bitcasts_and_bitcast(
-; CHECK-NEXT:    [[BC1:%.*]] = bitcast <4 x i32> %a to <2 x i64>
-; CHECK-NEXT:    [[BC2:%.*]] = bitcast <8 x i16> %b to <2 x i64>
-; CHECK-NEXT:    [[AND:%.*]] = and <2 x i64> [[BC2]], [[BC1]]
-; CHECK-NEXT:    [[BC3:%.*]] = bitcast <2 x i64> [[AND]] to <4 x i32>
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i16> %b to <4 x i32>
+; CHECK-NEXT:    [[BC3:%.*]] = and <4 x i32> [[TMP1]], %a
 ; CHECK-NEXT:    ret <4 x i32> [[BC3]]
 ;
   %bc1 = bitcast <4 x i32> %a to <2 x i64>
@@ -89,9 +87,8 @@
 
 define i128 @bitcast_or_bitcast(i128 %a, <2 x i64> %b) {
 ; CHECK-LABEL: @bitcast_or_bitcast(
-; CHECK-NEXT:    [[BC1:%.*]] = bitcast i128 %a to <2 x i64>
-; CHECK-NEXT:    [[OR:%.*]] = or <2 x i64> [[BC1]], %b
-; CHECK-NEXT:    [[BC2:%.*]] = bitcast <2 x i64> [[OR]] to i128
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i64> %b to i128
+; CHECK-NEXT:    [[BC2:%.*]] = or i128 [[TMP1]], %a
 ; CHECK-NEXT:    ret i128 [[BC2]]
 ;
   %bc1 = bitcast i128 %a to <2 x i64>
@@ -102,9 +99,8 @@
 
 define <4 x i32> @bitcast_xor_bitcast(<4 x i32> %a, i128 %b) {
 ; CHECK-LABEL: @bitcast_xor_bitcast(
-; CHECK-NEXT:    [[BC1:%.*]] = bitcast <4 x i32> %a to i128
-; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[BC1]], %b
-; CHECK-NEXT:    [[BC2:%.*]] = bitcast i128 [[XOR]] to <4 x i32>
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i128 %b to <4 x i32>
+; CHECK-NEXT:    [[BC2:%.*]] = xor <4 x i32> [[TMP1]], %a
 ; CHECK-NEXT:    ret <4 x i32> [[BC2]]
 ;
   %bc1 = bitcast <4 x i32> %a to i128
Index: lib/Transforms/InstCombine/InstCombineCasts.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -1778,6 +1778,37 @@
   return ExtractElementInst::Create(NewBC, ExtElt->getIndexOperand());
 }
 
+/// Change the type of a bitwise logic operation if we can eliminate a bitcast.
+static Instruction *foldBitCastBitwiseLogic(BitCastInst &BitCast,
+                                            InstCombiner::BuilderTy &Builder) {
+  BinaryOperator *BO;
+  if (!match(BitCast.getOperand(0), m_OneUse(m_BinOp(BO))))
+    return nullptr;
+
+  auto Opcode = BO->getOpcode();
+  if (Opcode != Instruction::And && Opcode != Instruction::Or &&
+      Opcode != Instruction::Xor)
+    return nullptr;
+
+  Type *DestTy = BitCast.getType();
+  Value *X;
+  if (match(BO->getOperand(0), m_OneUse(m_BitCast(m_Value(X)))) &&
+      X->getType() == DestTy && !isa<Constant>(X)) {
+    // bitcast(logic(bitcast(X), Y)) --> logic'(X, bitcast(Y))
+    Value *CastedOp1 = Builder.CreateBitCast(BO->getOperand(1), DestTy);
+    return BinaryOperator::Create(Opcode, X, CastedOp1);
+  }
+
+  if (match(BO->getOperand(1), m_OneUse(m_BitCast(m_Value(X)))) &&
+      X->getType() == DestTy && !isa<Constant>(X)) {
+    // bitcast(logic(Y, bitcast(X))) --> logic'(bitcast(Y), X)
+    Value *CastedOp0 = Builder.CreateBitCast(BO->getOperand(0), DestTy);
+    return BinaryOperator::Create(Opcode, CastedOp0, X);
+  }
+
+  return nullptr;
+}
+
 /// Check if all users of CI are StoreInsts.
 static bool hasStoreUsersOnly(CastInst &CI) {
   for (User *U : CI.users()) {
@@ -2030,6 +2061,9 @@
   if (Instruction *I = canonicalizeBitCastExtElt(CI, *this, DL))
     return I;
 
+  if (Instruction *I = foldBitCastBitwiseLogic(CI, *Builder))
+    return I;
+
   if (SrcTy->isPointerTy())
     return commonPointerCastTransforms(CI);
   return commonCastTransforms(CI);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D26641.77892.patch
Type: text/x-patch
Size: 3769 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161114/68c3c8d4/attachment.bin>


More information about the llvm-commits mailing list