From: Sanjay Patel Date: Thu, 3 Mar 2016 19:19:04 +0000 (+0000) Subject: [InstCombine] transform bitcasted bitwise logic ops with constants (PR26702) X-Git-Tag: llvmorg-3.9.0-rc1~12540 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9bba75084b7bde6a6215d616f664d3d2486f4871;p=platform%2Fupstream%2Fllvm.git [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, %not = xor <4 x i32> %lobit, %bc = bitcast <4 x i32> %not to <2 x i64> %notnot = xor <2 x i64> %bc, %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, ret <4 x i32> %lobit } Differential Revision: http://reviews.llvm.org/D17583 llvm-svn: 262645 --- diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index d19a022..4a6e99c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1251,21 +1251,42 @@ Instruction *InstCombiner::foldCastedBitwiseLogic(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); CastInst *Cast0 = dyn_cast(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(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)) diff --git a/llvm/test/Transforms/InstCombine/bitcast-bigendian.ll b/llvm/test/Transforms/InstCombine/bitcast-bigendian.ll index 4042dad..f558ecc 100644 --- a/llvm/test/Transforms/InstCombine/bitcast-bigendian.ll +++ b/llvm/test/Transforms/InstCombine/bitcast-bigendian.ll @@ -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(<1 x i64> %a) { 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, +; CHECK-NEXT: %t21 = xor <1 x i64> %a, +; 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 i32> %a) { 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, +; 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(i64 %a) { 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, +; CHECK-NEXT: %t21 = or i64 %a, 4294967298 +; CHECK-NEXT: %t2 = bitcast i64 %t21 to <2 x i32> ; CHECK-NEXT: ret <2 x i32> %t2 } diff --git a/llvm/test/Transforms/InstCombine/bitcast.ll b/llvm/test/Transforms/InstCombine/bitcast.ll index 2215b67..254b611 100644 --- a/llvm/test/Transforms/InstCombine/bitcast.ll +++ b/llvm/test/Transforms/InstCombine/bitcast.ll @@ -30,8 +30,6 @@ define <2 x i32> @xor_two_vector_bitcasts(<1 x i64> %a, <1 x i64> %b) { ; 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(<1 x i64> %a) { 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, +; CHECK-NEXT: %t21 = xor <1 x i64> %a, +; 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 i32> %a) { 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, +; 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(i64 %a) { 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, +; CHECK-NEXT: %t21 = or i64 %a, 8589934593 +; CHECK-NEXT: %t2 = bitcast i64 %t21 to <2 x i32> ; CHECK-NEXT: ret <2 x i32> %t2 }