[llvm] r262645 - [InstCombine] transform bitcasted bitwise logic ops with constants (PR26702)

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 3 11:19:04 PST 2016


Author: spatel
Date: Thu Mar  3 13:19:04 2016
New Revision: 262645

URL: http://llvm.org/viewvc/llvm-project?rev=262645&view=rev
Log:
[InstCombine] transform bitcasted bitwise logic ops with constants (PR26702)

Given that we're not actually reducing the instruction count in the included
regression tests, I think we would call this a canonicalization step.

The motivation comes from the example in PR26702:
https://llvm.org/bugs/show_bug.cgi?id=26702

If we hoist the bitwise logic ahead of the bitcast, the previously unoptimizable
example of:

define <4 x i32> @is_negative(<4 x i32> %x) {
  %lobit = ashr <4 x i32> %x, <i32 31, i32 31, i32 31, i32 31>
  %not = xor <4 x i32> %lobit, <i32 -1, i32 -1, i32 -1, i32 -1>
  %bc = bitcast <4 x i32> %not to <2 x i64>
  %notnot = xor <2 x i64> %bc, <i64 -1, i64 -1>
  %bc2 = bitcast <2 x i64> %notnot to <4 x i32>
  ret <4 x i32> %bc2
}

Simplifies to the expected:

define <4 x i32> @is_negative(<4 x i32> %x) {
  %lobit = ashr <4 x i32> %x, <i32 31, i32 31, i32 31, i32 31>
  ret <4 x i32> %lobit
}

Differential Revision: http://reviews.llvm.org/D17583


Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/trunk/test/Transforms/InstCombine/bitcast-bigendian.ll
    llvm/trunk/test/Transforms/InstCombine/bitcast.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp?rev=262645&r1=262644&r2=262645&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp Thu Mar  3 13:19:04 2016
@@ -1251,21 +1251,42 @@ Instruction *InstCombiner::foldCastedBit
 
   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
   CastInst *Cast0 = dyn_cast<CastInst>(Op0);
+  if (!Cast0)
+    return nullptr;
+
+  // This must be a cast from an integer or integer vector source type to allow
+  // transformation of the logic operation to the source type.
+  Type *DestTy = I.getType();
+  Type *SrcTy = Cast0->getSrcTy();
+  if (!SrcTy->isIntOrIntVectorTy())
+    return nullptr;
+
+  // If one operand is a bitcast and the other is a constant, move the logic
+  // operation ahead of the bitcast. That is, do the logic operation in the
+  // original type. This can eliminate useless bitcasts and allow normal
+  // combines that would otherwise be impeded by the bitcast. Canonicalization
+  // ensures that if there is a constant operand, it will be the second operand.
+  Value *BC = nullptr;
+  Constant *C = nullptr;
+  if ((match(Op0, m_BitCast(m_Value(BC))) && match(Op1, m_Constant(C)))) {
+    // A bitcast of a constant will be removed.
+    Value *NewConstant = Builder->CreateBitCast(C, SrcTy);
+    Value *NewOp = Builder->CreateBinOp(LogicOpc, BC, NewConstant, I.getName());
+    return CastInst::CreateBitOrPointerCast(NewOp, DestTy);
+  }
+
   CastInst *Cast1 = dyn_cast<CastInst>(Op1);
-  if (!Cast0 || !Cast1)
+  if (!Cast1)
     return nullptr;
 
-  // The casts must be of the same type, and this must be a cast from an integer
-  // or integer vector source type.
+  // Both operands of the logic operation are casts. The casts must be of the
+  // same type for reduction.
   auto CastOpcode = Cast0->getOpcode();
-  Type *SrcTy = Cast0->getSrcTy();
-  if ((CastOpcode != Cast1->getOpcode()) || (SrcTy != Cast1->getSrcTy()) ||
-      !SrcTy->isIntOrIntVectorTy())
+  if (CastOpcode != Cast1->getOpcode() || SrcTy != Cast1->getSrcTy())
     return nullptr;
 
   Value *Cast0Src = Cast0->getOperand(0);
   Value *Cast1Src = Cast1->getOperand(0);
-  Type *DestTy = I.getType();
 
   // fold (logic (cast A), (cast B)) -> (cast (logic A, B))
 

Modified: llvm/trunk/test/Transforms/InstCombine/bitcast-bigendian.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/bitcast-bigendian.ll?rev=262645&r1=262644&r2=262645&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/bitcast-bigendian.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/bitcast-bigendian.ll Thu Mar  3 13:19:04 2016
@@ -90,8 +90,6 @@ define <2 x float> @test6(float %A){
 ; CHECK: ret
 }
 
-; FIXME: Do the logic in the original type for the following 3 tests.
-
 ; Verify that 'xor' of vector and constant is done as a vector bitwise op before the bitcast.
 
 define <2 x i32> @xor_bitcast_vec_to_vec(<1 x i64> %a) {
@@ -100,8 +98,8 @@ define <2 x i32> @xor_bitcast_vec_to_vec
   ret <2 x i32> %t2
 
 ; CHECK-LABEL: @xor_bitcast_vec_to_vec(
-; CHECK-NEXT:  %t1 = bitcast <1 x i64> %a to <2 x i32>
-; CHECK-NEXT:  %t2 = xor <2 x i32> %t1, <i32 1, i32 2>
+; CHECK-NEXT:  %t21 = xor <1 x i64> %a, <i64 4294967298> 
+; CHECK-NEXT:  %t2 = bitcast <1 x i64> %t21 to <2 x i32>
 ; CHECK-NEXT:  ret <2 x i32> %t2
 }
 
@@ -113,8 +111,8 @@ define i64 @and_bitcast_vec_to_int(<2 x
   ret i64 %t2
 
 ; CHECK-LABEL: @and_bitcast_vec_to_int(
-; CHECK-NEXT:  %t1 = bitcast <2 x i32> %a to i64
-; CHECK-NEXT:  %t2 = and i64 %t1, 3
+; CHECK-NEXT:  %t21 = and <2 x i32> %a, <i32 0, i32 3>
+; CHECK-NEXT:  %t2 = bitcast <2 x i32> %t21 to i64
 ; CHECK-NEXT:  ret i64 %t2
 }
 
@@ -126,8 +124,8 @@ define <2 x i32> @or_bitcast_int_to_vec(
   ret <2 x i32> %t2
 
 ; CHECK-LABEL: @or_bitcast_int_to_vec(
-; CHECK-NEXT:  %t1 = bitcast i64 %a to <2 x i32>
-; CHECK-NEXT:  %t2 = or <2 x i32> %t1, <i32 1, i32 2>
+; CHECK-NEXT:  %t21 = or i64 %a, 4294967298
+; CHECK-NEXT:  %t2 = bitcast i64 %t21 to <2 x i32>
 ; CHECK-NEXT:  ret <2 x i32> %t2
 }
 

Modified: llvm/trunk/test/Transforms/InstCombine/bitcast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/bitcast.ll?rev=262645&r1=262644&r2=262645&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/bitcast.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/bitcast.ll Thu Mar  3 13:19:04 2016
@@ -30,8 +30,6 @@ define <2 x i32> @xor_two_vector_bitcast
 ; CHECK-NEXT:  ret <2 x i32> %t3
 }
 
-; FIXME: Do the logic in the original type for the following 3 tests.
-
 ; Verify that 'xor' of vector and constant is done as a vector bitwise op before the bitcast.
 
 define <2 x i32> @xor_bitcast_vec_to_vec(<1 x i64> %a) {
@@ -40,8 +38,8 @@ define <2 x i32> @xor_bitcast_vec_to_vec
   ret <2 x i32> %t2
 
 ; CHECK-LABEL: @xor_bitcast_vec_to_vec(
-; CHECK-NEXT:  %t1 = bitcast <1 x i64> %a to <2 x i32>
-; CHECK-NEXT:  %t2 = xor <2 x i32> %t1, <i32 1, i32 2>
+; CHECK-NEXT:  %t21 = xor <1 x i64> %a, <i64 8589934593> 
+; CHECK-NEXT:  %t2 = bitcast <1 x i64> %t21 to <2 x i32>
 ; CHECK-NEXT:  ret <2 x i32> %t2
 }
 
@@ -53,8 +51,8 @@ define i64 @and_bitcast_vec_to_int(<2 x
   ret i64 %t2
 
 ; CHECK-LABEL: @and_bitcast_vec_to_int(
-; CHECK-NEXT:  %t1 = bitcast <2 x i32> %a to i64
-; CHECK-NEXT:  %t2 = and i64 %t1, 3
+; CHECK-NEXT:  %t21 = and <2 x i32> %a, <i32 3, i32 0>
+; CHECK-NEXT:  %t2 = bitcast <2 x i32> %t21 to i64
 ; CHECK-NEXT:  ret i64 %t2
 }
 
@@ -66,8 +64,8 @@ define <2 x i32> @or_bitcast_int_to_vec(
   ret <2 x i32> %t2
 
 ; CHECK-LABEL: @or_bitcast_int_to_vec(
-; CHECK-NEXT:  %t1 = bitcast i64 %a to <2 x i32>
-; CHECK-NEXT:  %t2 = or <2 x i32> %t1, <i32 1, i32 2>
+; CHECK-NEXT:  %t21 = or i64 %a, 8589934593
+; CHECK-NEXT:  %t2 = bitcast i64 %t21 to <2 x i32>
 ; CHECK-NEXT:  ret <2 x i32> %t2
 }
 




More information about the llvm-commits mailing list