From 280d9f7d12cc44c267c9ba77ec24d65d8bd82d28 Mon Sep 17 00:00:00 2001 From: XChy Date: Sat, 6 Sep 2025 17:06:46 +0800 Subject: [PATCH 1/4] Precommit tests --- .../VectorCombine/X86/bitop-of-castops.ll | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/llvm/test/Transforms/VectorCombine/X86/bitop-of-castops.ll b/llvm/test/Transforms/VectorCombine/X86/bitop-of-castops.ll index ca707ca08f169..fe62f91480cd2 100644 --- a/llvm/test/Transforms/VectorCombine/X86/bitop-of-castops.ll +++ b/llvm/test/Transforms/VectorCombine/X86/bitop-of-castops.ll @@ -420,3 +420,63 @@ define <4 x i32> @or_zext_nneg_multiconstant(<4 x i8> %a) { %or = or <4 x i32> %z1, ret <4 x i32> %or } + +; Negative test: bitcast from scalar float to vector int (optimization should not apply) +define <2 x i16> @and_bitcast_f32_to_v2i16_constant(float %a) { +; CHECK-LABEL: @and_bitcast_f32_to_v2i16_constant( +; CHECK-NEXT: [[BC2:%.*]] = bitcast float [[B:%.*]] to <2 x i16> +; CHECK-NEXT: [[AND:%.*]] = and <2 x i16> , [[BC2]] +; CHECK-NEXT: ret <2 x i16> [[AND]] +; + %bc = bitcast float %a to <2 x i16> + %and = and <2 x i16> , %bc + ret <2 x i16> %and +} + +; Negative test: bitcast from vector float to scalar int (optimization should not apply) +define i64 @and_bitcast_v2f32_to_i64_constant(<2 x float> %a) { +; CHECK-LABEL: @and_bitcast_v2f32_to_i64_constant( +; CHECK-NEXT: [[BC2:%.*]] = bitcast <2 x float> [[B:%.*]] to i64 +; CHECK-NEXT: [[AND:%.*]] = and i64 123, [[BC2]] +; CHECK-NEXT: ret i64 [[AND]] +; + %bc = bitcast <2 x float> %a to i64 + %and = and i64 123, %bc + ret i64 %and +} + +; Test no-op bitcast +define i16 @xor_bitcast_i16_to_i16_constant(i16 %a) { +; CHECK-LABEL: @xor_bitcast_i16_to_i16_constant( +; CHECK-NEXT: [[BC2:%.*]] = bitcast i16 [[B:%.*]] to i16 +; CHECK-NEXT: [[OR:%.*]] = xor i16 123, [[BC2]] +; CHECK-NEXT: ret i16 [[OR]] +; + %bc = bitcast i16 %a to i16 + %or = xor i16 123, %bc + ret i16 %or +} + +; Test bitwise operations with integer vector to integer bitcast +define <16 x i1> @xor_bitcast_i16_to_v16i1_constant(i16 %a) { +; CHECK-LABEL: @xor_bitcast_i16_to_v16i1_constant( +; CHECK-NEXT: [[BC2:%.*]] = bitcast i16 [[B:%.*]] to <16 x i1> +; CHECK-NEXT: [[OR:%.*]] = xor <16 x i1> [[BC2]], splat (i1 true) +; CHECK-NEXT: ret <16 x i1> [[OR]] +; + %bc = bitcast i16 %a to <16 x i1> + %or = xor <16 x i1> %bc, splat (i1 true) + ret <16 x i1> %or +} + +; Test bitwise operations with integer vector to integer bitcast +define i16 @or_bitcast_v16i1_to_i16_constant(<16 x i1> %a) { +; CHECK-LABEL: @or_bitcast_v16i1_to_i16_constant( +; CHECK-NEXT: [[BC2:%.*]] = bitcast <16 x i1> [[B:%.*]] to i16 +; CHECK-NEXT: [[OR:%.*]] = or i16 [[BC2]], 3 +; CHECK-NEXT: ret i16 [[OR]] +; + %bc = bitcast <16 x i1> %a to i16 + %or = or i16 %bc, 3 + ret i16 %or +} From 3caa1e152b591ecddabe433f66abc1d8b43110b0 Mon Sep 17 00:00:00 2001 From: XChy Date: Sat, 6 Sep 2025 17:14:56 +0800 Subject: [PATCH 2/4] [VectorCombine] Relax vector type constraint in foldBitOpOfCastConstant --- .../Transforms/Vectorize/VectorCombine.cpp | 27 +++++++++---------- .../VectorCombine/X86/bitop-of-castops.ll | 6 ++--- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index 6e46547b15b2b..cea818350103a 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -1013,19 +1013,20 @@ bool VectorCombine::foldBitOpOfCastConstant(Instruction &I) { Value *LHSSrc = LHSCast->getOperand(0); - // Only handle vector types with integer elements - auto *SrcVecTy = dyn_cast(LHSSrc->getType()); - auto *DstVecTy = dyn_cast(I.getType()); - if (!SrcVecTy || !DstVecTy) + // Only handle vector types with integer elements if the cast is not bitcast + auto *SrcTy = LHSSrc->getType(); + auto *DstTy = I.getType(); + if (CastOpcode != Instruction::BitCast && + (!isa(SrcTy) || !!isa(DstTy))) return false; - if (!SrcVecTy->getScalarType()->isIntegerTy() || - !DstVecTy->getScalarType()->isIntegerTy()) + if (!SrcTy->getScalarType()->isIntegerTy() || + !DstTy->getScalarType()->isIntegerTy()) return false; // Find the constant InvC, such that castop(InvC) equals to C. PreservedCastFlags RHSFlags; - Constant *InvC = getLosslessInvCast(C, SrcVecTy, CastOpcode, *DL, RHSFlags); + Constant *InvC = getLosslessInvCast(C, SrcTy, CastOpcode, *DL, RHSFlags); if (!InvC) return false; @@ -1034,20 +1035,18 @@ bool VectorCombine::foldBitOpOfCastConstant(Instruction &I) { // NewCost = bitlogic + cast // Calculate specific costs for each cast with instruction context - InstructionCost LHSCastCost = - TTI.getCastInstrCost(CastOpcode, DstVecTy, SrcVecTy, - TTI::CastContextHint::None, CostKind, LHSCast); + InstructionCost LHSCastCost = TTI.getCastInstrCost( + CastOpcode, DstTy, SrcTy, TTI::CastContextHint::None, CostKind, LHSCast); InstructionCost OldCost = - TTI.getArithmeticInstrCost(I.getOpcode(), DstVecTy, CostKind) + - LHSCastCost; + TTI.getArithmeticInstrCost(I.getOpcode(), DstTy, CostKind) + LHSCastCost; // For new cost, we can't provide an instruction (it doesn't exist yet) InstructionCost GenericCastCost = TTI.getCastInstrCost( - CastOpcode, DstVecTy, SrcVecTy, TTI::CastContextHint::None, CostKind); + CastOpcode, DstTy, SrcTy, TTI::CastContextHint::None, CostKind); InstructionCost NewCost = - TTI.getArithmeticInstrCost(I.getOpcode(), SrcVecTy, CostKind) + + TTI.getArithmeticInstrCost(I.getOpcode(), SrcTy, CostKind) + GenericCastCost; // Account for multi-use casts using specific costs diff --git a/llvm/test/Transforms/VectorCombine/X86/bitop-of-castops.ll b/llvm/test/Transforms/VectorCombine/X86/bitop-of-castops.ll index fe62f91480cd2..c6253a7b858ad 100644 --- a/llvm/test/Transforms/VectorCombine/X86/bitop-of-castops.ll +++ b/llvm/test/Transforms/VectorCombine/X86/bitop-of-castops.ll @@ -460,9 +460,9 @@ define i16 @xor_bitcast_i16_to_i16_constant(i16 %a) { ; Test bitwise operations with integer vector to integer bitcast define <16 x i1> @xor_bitcast_i16_to_v16i1_constant(i16 %a) { ; CHECK-LABEL: @xor_bitcast_i16_to_v16i1_constant( -; CHECK-NEXT: [[BC2:%.*]] = bitcast i16 [[B:%.*]] to <16 x i1> -; CHECK-NEXT: [[OR:%.*]] = xor <16 x i1> [[BC2]], splat (i1 true) -; CHECK-NEXT: ret <16 x i1> [[OR]] +; CHECK-NEXT: [[B:%.*]] = xor i16 [[A:%.*]], -1 +; CHECK-NEXT: [[BC2:%.*]] = bitcast i16 [[B]] to <16 x i1> +; CHECK-NEXT: ret <16 x i1> [[BC2]] ; %bc = bitcast i16 %a to <16 x i1> %or = xor <16 x i1> %bc, splat (i1 true) From 67e3093fd603ea88a8d7fb4fb6427b52795429b1 Mon Sep 17 00:00:00 2001 From: XChy Date: Sun, 7 Sep 2025 21:24:16 +0800 Subject: [PATCH 3/4] update comment --- llvm/lib/Transforms/Vectorize/VectorCombine.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index cea818350103a..296416c03a9e5 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -1013,17 +1013,20 @@ bool VectorCombine::foldBitOpOfCastConstant(Instruction &I) { Value *LHSSrc = LHSCast->getOperand(0); - // Only handle vector types with integer elements if the cast is not bitcast auto *SrcTy = LHSSrc->getType(); auto *DstTy = I.getType(); + // Bitcasts can handle scalar/vector mixes, such as i16 -> <16 x i1>. + // Other casts only handle vector types with integer elements. if (CastOpcode != Instruction::BitCast && - (!isa(SrcTy) || !!isa(DstTy))) + (!isa(SrcTy) || !isa(DstTy))) return false; + // Only integer scalar/vector values are legal for bitwise logic operations. if (!SrcTy->getScalarType()->isIntegerTy() || !DstTy->getScalarType()->isIntegerTy()) return false; + // Find the constant InvC, such that castop(InvC) equals to C. PreservedCastFlags RHSFlags; Constant *InvC = getLosslessInvCast(C, SrcTy, CastOpcode, *DL, RHSFlags); From 11f3332dedcf1693e79e948dbb718660830ec9c3 Mon Sep 17 00:00:00 2001 From: XChy Date: Sun, 7 Sep 2025 21:30:30 +0800 Subject: [PATCH 4/4] format --- llvm/lib/Transforms/Vectorize/VectorCombine.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index 296416c03a9e5..b1c7a2682785b 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -1026,7 +1026,6 @@ bool VectorCombine::foldBitOpOfCastConstant(Instruction &I) { !DstTy->getScalarType()->isIntegerTy()) return false; - // Find the constant InvC, such that castop(InvC) equals to C. PreservedCastFlags RHSFlags; Constant *InvC = getLosslessInvCast(C, SrcTy, CastOpcode, *DL, RHSFlags);