forked from OSchip/llvm-project
[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 llvm-svn: 262645
This commit is contained in:
parent
dd12e9a8c0
commit
9bba75084b
|
@ -1251,21 +1251,42 @@ Instruction *InstCombiner::foldCastedBitwiseLogic(BinaryOperator &I) {
|
|||
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
CastInst *Cast0 = dyn_cast<CastInst>(Op0);
|
||||
CastInst *Cast1 = dyn_cast<CastInst>(Op1);
|
||||
if (!Cast0 || !Cast1)
|
||||
if (!Cast0)
|
||||
return nullptr;
|
||||
|
||||
// The casts must be of the same type, and this must be a cast from an integer
|
||||
// or integer vector source type.
|
||||
auto CastOpcode = Cast0->getOpcode();
|
||||
// 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 ((CastOpcode != Cast1->getOpcode()) || (SrcTy != Cast1->getSrcTy()) ||
|
||||
!SrcTy->isIntOrIntVectorTy())
|
||||
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 (!Cast1)
|
||||
return nullptr;
|
||||
|
||||
// Both operands of the logic operation are casts. The casts must be of the
|
||||
// same type for reduction.
|
||||
auto CastOpcode = Cast0->getOpcode();
|
||||
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))
|
||||
|
||||
|
|
|
@ -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, <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 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, <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(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, <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
|
||||
}
|
||||
|
||||
|
|
|
@ -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, <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 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, <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(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, <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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue