@@ -563,3 +563,46 @@ void vector_shuffle_dynamic_mask_test() {
563563
564564  //  LLVM: {{.*}} = and <6 x i32> {{.*}}, splat (i32 7)
565565}
566+ 
567+ //  Test for arrays of 3-component extended vectors
568+ //  This documents how vec3 arrays are handled in memory accesses
569+ //  Original CodeGen treats vec3 as vec4 for aligned memory access
570+ //  See issue #685
571+ //  CIR: cir.func dso_local {{@.*test_vec3_array.*}}
572+ //  LLVM: define dso_local void {{@.*test_vec3_array.*}}
573+ void  test_vec3_array () {
574+   vi3 arr[4 ] = {};
575+   //  CIR: cir.alloca !cir.array<!cir.vector<!s32i x 3> x 4>, !cir.ptr<!cir.array<!cir.vector<!s32i x 3> x 4>>, ["arr"]
576+   //  LLVM: alloca [4 x <3 x i32>], i64 1, align 16
577+ 
578+   vi3 *ptr = &arr[0 ];
579+   //  CIR: cir.get_element{{.*}}!cir.array<!cir.vector<!s32i x 3> x 4>
580+   //  LLVM: getelementptr [4 x <3 x i32>]
581+   
582+   //  Key behavior: Loading from array element shows vec3->vec4 optimization
583+   arr[0 ] + arr[1 ];
584+   //  CIR: %[[#PTR0:]] = cir.get_element{{.*}}!cir.ptr<!cir.vector<!s32i x 3>>
585+   //  CIR-NEXT: %[[#PTR0_V4:]] = cir.cast bitcast %[[#PTR0]] : !cir.ptr<!cir.vector<!s32i x 3>> -> !cir.ptr<!cir.vector<!s32i x 4>>
586+   //  CIR-NEXT: %[[#V4_0:]] = cir.load{{.*}}%[[#PTR0_V4]] : !cir.ptr<!cir.vector<!s32i x 4>>, !cir.vector<!s32i x 4>
587+   //  CIR-NEXT: %[[#POISON0:]] = cir.const #cir.poison : !cir.vector<!s32i x 4>
588+   //  CIR-NEXT: %[[#V3_0:]] = cir.vec.shuffle(%[[#V4_0]], %[[#POISON0]] : !cir.vector<!s32i x 4>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<2> : !s32i] : !cir.vector<!s32i x 3>
589+   
590+   //  LLVM: %[[#GEP0:]] = getelementptr [4 x <3 x i32>], ptr %{{.+}}, i32 0, i64 0
591+   //  LLVM-NEXT: %[[#LOAD_V4_0:]] = load <4 x i32>, ptr %[[#GEP0]], align 16
592+   //  LLVM-NEXT: %[[#LOAD_V3_0:]] = shufflevector <4 x i32> %[[#LOAD_V4_0]], <4 x i32> poison, <3 x i32> <i32 0, i32 1, i32 2>
593+ 
594+   //  Same pattern for arr[1]
595+   //  CIR: %[[#PTR1:]] = cir.get_element{{.*}}!cir.ptr<!cir.vector<!s32i x 3>>
596+   //  CIR-NEXT: %[[#PTR1_V4:]] = cir.cast bitcast %[[#PTR1]] : !cir.ptr<!cir.vector<!s32i x 3>> -> !cir.ptr<!cir.vector<!s32i x 4>>
597+   //  CIR-NEXT: %[[#V4_1:]] = cir.load{{.*}}%[[#PTR1_V4]] : !cir.ptr<!cir.vector<!s32i x 4>>, !cir.vector<!s32i x 4>
598+   //  CIR-NEXT: %[[#POISON1:]] = cir.const #cir.poison : !cir.vector<!s32i x 4>
599+   //  CIR-NEXT: %[[#V3_1:]] = cir.vec.shuffle(%[[#V4_1]], %[[#POISON1]] : !cir.vector<!s32i x 4>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<2> : !s32i] : !cir.vector<!s32i x 3>
600+   //  CIR: cir.binop(add, %[[#V3_0]], %[[#V3_1]]) : !cir.vector<!s32i x 3>
601+   
602+   //  LLVM: %[[#GEP1:]] = getelementptr [4 x <3 x i32>], ptr %{{.+}}, i32 0, i64 1
603+   //  LLVM-NEXT: %[[#LOAD_V4_1:]] = load <4 x i32>, ptr %[[#GEP1]], align 16
604+   //  LLVM-NEXT: %[[#LOAD_V3_1:]] = shufflevector <4 x i32> %[[#LOAD_V4_1]], <4 x i32> poison, <3 x i32> <i32 0, i32 1, i32 2>
605+   //  LLVM: add <3 x i32> %[[#LOAD_V3_0]], %[[#LOAD_V3_1]]
606+   
607+   //  Note: Array element stores (arr[i] = value) are not yet implemented (NYI at CIRGenExpr.cpp:640)
608+ }
0 commit comments