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))
; 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) {
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
}
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
}
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
}
; 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) {
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
}
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
}
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
}