@@ -499,3 +499,35 @@ define <1 x i64> @bitcast_noshift_vector_wrong_type(<2 x float> %v1, <1 x i64> %
499499 %r = shl <1 x i64 > %v2 , %b
500500 ret <1 x i64 > %r
501501}
502+
503+ ; Test that verifies correct handling of known bits when bitcasting from a smaller vector
504+ ; to a larger one (e.g., <2 x i32> to <8 x i8>). Previously, only the subscale portion
505+ ; (e.g., 4 elements) was checked instead of the full demanded vector width (8 elements),
506+ ; leading to incorrect known bits and removal of the `ashr` instruction.
507+
508+ define <8 x i8 > @bitcast_knownbits_subscale_miscompile (i32 %x ) {
509+ ; CHECK-LABEL: @bitcast_knownbits_subscale_miscompile(
510+ ; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[X:%.*]], -256
511+ ; CHECK-NEXT: [[BITCAST:%.*]] = bitcast i32 [[MASKED]] to <4 x i8>
512+ ; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x i8> [[BITCAST]], i32 3
513+ ; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[EXTRACT]], -113
514+ ; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
515+ ; CHECK-NEXT: [[INSERT:%.*]] = insertelement <2 x i32> poison, i32 [[MASKED]], i32 0
516+ ; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x i32> [[INSERT]], <2 x i32> poison, <2 x i32> zeroinitializer
517+ ; CHECK-NEXT: [[VEC:%.*]] = bitcast <2 x i32> [[SPLAT]] to <8 x i8>
518+ ; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <8 x i8> [[VEC]], <8 x i8> zeroinitializer, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 0, i32 0, i32 0, i32 0>
519+ ; CHECK-NEXT: [[SHR:%.*]] = ashr <8 x i8> [[SHUF]], splat (i8 1)
520+ ; CHECK-NEXT: ret <8 x i8> [[SHR]]
521+ ;
522+ %masked = and i32 %x , u0xFFFFFF00
523+ %bitcast = bitcast i32 %masked to <4 x i8 >
524+ %extract = extractelement <4 x i8 > %bitcast , i32 3
525+ %cond = icmp eq i8 %extract , u0x8F
526+ call void @llvm.assume (i1 %cond )
527+ %insert = insertelement <2 x i32 > poison, i32 %masked , i32 0
528+ %splat = shufflevector <2 x i32 > %insert , <2 x i32 > poison, <2 x i32 > splat (i32 0 )
529+ %vec = bitcast <2 x i32 > %splat to <8 x i8 >
530+ %shuf = shufflevector <8 x i8 > %vec , <8 x i8 > zeroinitializer , <8 x i32 > <i32 7 , i32 7 , i32 7 , i32 7 , i32 0 , i32 0 , i32 0 , i32 0 >
531+ %shr = ashr <8 x i8 > %shuf , splat (i8 1 )
532+ ret <8 x i8 > %shr
533+ }
0 commit comments