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();
+ if (!DestTy->getScalarType()->isIntegerTy())
+ return nullptr;
+
+ // FIXME: This transform is restricted to vector types to avoid backend
+ // problems caused by creating potentially illegal operations. If a fix-up is
+ // added to handle that situation, we can remove this check.
+ if (!DestTy->isVectorTy() || !BO->getType()->isVectorTy())
+ return nullptr;
+
+ 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()) {
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);
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>
ret <4 x i32> %bc3
}
+; The destination must have an integer element type.
+; FIXME: We can still eliminate one bitcast in this test by doing the logic op
+; in the type of the input that has an integer element type.
+
+define <4 x float> @bitcasts_and_bitcast_to_fp(<4 x float> %a, <8 x i16> %b) {
+; CHECK-LABEL: @bitcasts_and_bitcast_to_fp(
+; CHECK-NEXT: [[BC1:%.*]] = bitcast <4 x float> %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 float>
+; CHECK-NEXT: ret <4 x float> [[BC3]]
+;
+ %bc1 = bitcast <4 x float> %a to <2 x i64>
+ %bc2 = bitcast <8 x i16> %b to <2 x i64>
+ %and = and <2 x i64> %bc2, %bc1
+ %bc3 = bitcast <2 x i64> %and to <4 x float>
+ ret <4 x float> %bc3
+}
+
+; FIXME: Transform limited from changing vector op to integer op to avoid codegen problems.
+
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>
ret i128 %bc2
}
+; FIXME: Transform limited from changing integer op to vector op to avoid codegen problems.
+
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