diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -2377,8 +2377,8 @@ InstCombiner::BuilderTy &Builder) { Type *DestTy = BitCast.getType(); BinaryOperator *BO; - if (!DestTy->isIntOrIntVectorTy() || - !match(BitCast.getOperand(0), m_OneUse(m_BinOp(BO))) || + + if (!match(BitCast.getOperand(0), m_OneUse(m_BinOp(BO))) || !BO->isBitwiseLogicOp()) return nullptr; @@ -2388,6 +2388,32 @@ if (!DestTy->isVectorTy() || !BO->getType()->isVectorTy()) return nullptr; + if (DestTy->isFPOrFPVectorTy()) { + Value *X, *Y; + // bitcast(logic(bitcast(X), bitcast(Y))) -> bitcast'(logic(bitcast'(X), Y)) + if (match(BO->getOperand(0), m_OneUse(m_BitCast(m_Value(X)))) && + match(BO->getOperand(1), m_OneUse(m_BitCast(m_Value(Y))))) { + if (X->getType()->isFPOrFPVectorTy() && + Y->getType()->isIntOrIntVectorTy()) { + Value *CastedOp = + Builder.CreateBitCast(BO->getOperand(0), Y->getType()); + Value *NewBO = Builder.CreateBinOp(BO->getOpcode(), CastedOp, Y); + return CastInst::CreateBitOrPointerCast(NewBO, DestTy); + } + if (X->getType()->isIntOrIntVectorTy() && + Y->getType()->isFPOrFPVectorTy()) { + Value *CastedOp = + Builder.CreateBitCast(BO->getOperand(1), X->getType()); + Value *NewBO = Builder.CreateBinOp(BO->getOpcode(), CastedOp, X); + return CastInst::CreateBitOrPointerCast(NewBO, DestTy); + } + } + return nullptr; + } + + if (!DestTy->isIntOrIntVectorTy()) + return nullptr; + Value *X; if (match(BO->getOperand(0), m_OneUse(m_BitCast(m_Value(X)))) && X->getType() == DestTy && !isa(X)) { diff --git a/llvm/test/Transforms/InstCombine/bitcast-inseltpoison.ll b/llvm/test/Transforms/InstCombine/bitcast-inseltpoison.ll --- a/llvm/test/Transforms/InstCombine/bitcast-inseltpoison.ll +++ b/llvm/test/Transforms/InstCombine/bitcast-inseltpoison.ll @@ -130,16 +130,11 @@ 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: [[TMP1:%.*]] = bitcast <4 x float> [[A:%.*]] to <8 x i16> +; CHECK-NEXT: [[TMP2:%.*]] = and <8 x i16> [[TMP1]], [[B:%.*]] +; CHECK-NEXT: [[BC3:%.*]] = bitcast <8 x i16> [[TMP2]] to <4 x float> ; CHECK-NEXT: ret <4 x float> [[BC3]] ; %bc1 = bitcast <4 x float> %a to <2 x i64> diff --git a/llvm/test/Transforms/InstCombine/bitcast.ll b/llvm/test/Transforms/InstCombine/bitcast.ll --- a/llvm/test/Transforms/InstCombine/bitcast.ll +++ b/llvm/test/Transforms/InstCombine/bitcast.ll @@ -4,6 +4,8 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-darwin10.0.0" +declare void @use_vec(<2 x i64>) + ; Bitcasts between vectors and scalars are valid. ; PR4487 define i32 @test1(i64 %a) { @@ -130,16 +132,11 @@ 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: [[TMP1:%.*]] = bitcast <4 x float> [[A:%.*]] to <8 x i16> +; CHECK-NEXT: [[TMP2:%.*]] = and <8 x i16> [[TMP1]], [[B:%.*]] +; CHECK-NEXT: [[BC3:%.*]] = bitcast <8 x i16> [[TMP2]] to <4 x float> ; CHECK-NEXT: ret <4 x float> [[BC3]] ; %bc1 = bitcast <4 x float> %a to <2 x i64> @@ -149,17 +146,49 @@ ret <4 x float> %bc3 } -define <4 x float> @bitcasts_or_bitcast_to_fp(<4 x float> %a, <8 x i16> %b) { +define <2 x double> @bitcasts_or_bitcast_to_fp(<4 x float> %a, <8 x i16> %b) { ; CHECK-LABEL: @bitcasts_or_bitcast_to_fp( +; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x float> [[A:%.*]] to <8 x i16> +; CHECK-NEXT: [[TMP2:%.*]] = or <8 x i16> [[TMP1]], [[B:%.*]] +; CHECK-NEXT: [[BC3:%.*]] = bitcast <8 x i16> [[TMP2]] to <2 x double> +; CHECK-NEXT: ret <2 x double> [[BC3]] +; + %bc1 = bitcast <4 x float> %a to <2 x i64> + %bc2 = bitcast <8 x i16> %b to <2 x i64> + %and = or <2 x i64> %bc1, %bc2 + %bc3 = bitcast <2 x i64> %and to <2 x double> + ret <2 x double> %bc3 +} + +define <4 x float> @bitcasts_xor_bitcast_to_fp(<2 x double> %a, <8 x i16> %b) { +; CHECK-LABEL: @bitcasts_xor_bitcast_to_fp( +; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x double> [[A:%.*]] to <8 x i16> +; CHECK-NEXT: [[TMP2:%.*]] = xor <8 x i16> [[TMP1]], [[B:%.*]] +; CHECK-NEXT: [[BC3:%.*]] = bitcast <8 x i16> [[TMP2]] to <4 x float> +; CHECK-NEXT: ret <4 x float> [[BC3]] +; + %bc1 = bitcast <8 x i16> %b to <2 x i64> + %bc2 = bitcast <2 x double> %a to <2 x i64> + %xor = xor <2 x i64> %bc2, %bc1 + %bc3 = bitcast <2 x i64> %xor to <4 x float> + ret <4 x float> %bc3 +} + +; Negative test + +define <4 x float> @bitcasts_and_bitcast_to_fp_multiuse(<4 x float> %a, <8 x i16> %b) { +; CHECK-LABEL: @bitcasts_and_bitcast_to_fp_multiuse( ; 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:%.*]] = or <2 x i64> [[BC1]], [[BC2]] +; CHECK-NEXT: call void @use_vec(<2 x i64> [[BC2]]) +; 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 = or <2 x i64> %bc1, %bc2 + call void @use_vec(<2 x i64> %bc2) + %and = and <2 x i64> %bc2, %bc1 %bc3 = bitcast <2 x i64> %and to <4 x float> ret <4 x float> %bc3 }