Hi,

I've written a simple function:

function testfun2()
    a = 0
    @inbounds @simd for i in UInt64(1):UInt64(1000)
        i = i - ((i >> 1) & 0x5555555555555555)
        a += ((i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333))
    end
    return a
end

I applies the same set of bit operations to a series of UInt64's and 
accumulates a result.

And know from the Intel blog on vectorisation, in the llvm code generated 
by julia there is a set of instructions to look out for that indicate 
vectorised code: vector.head and vector.ph:

I'm wondering why I don't see those instructions in the llvm generated for 
this function, I don't think I've violated any of the rules of writing 
loops that can be vectorised:

*julia> **@code_llvm testfun2()*


define %jl_value_t* @julia_testfun2_70900() #0 {

top:

  %0 = call %jl_value_t*** @jl_get_ptls_states() #1

  %1 = alloca [11 x %jl_value_t*], align 8

  %.sub = getelementptr inbounds [11 x %jl_value_t*], [11 x %jl_value_t*]* 
%1, i64 0, i64 0

  %2 = getelementptr [11 x %jl_value_t*], [11 x %jl_value_t*]* %1, i64 0, 
i64 8

  %3 = getelementptr [11 x %jl_value_t*], [11 x %jl_value_t*]* %1, i64 0, 
i64 2

  %a = getelementptr [11 x %jl_value_t*], [11 x %jl_value_t*]* %1, i64 0, 
i64 7

  %4 = bitcast %jl_value_t** %2 to i8*

  call void @llvm.memset.p0i8.i32(i8* %4, i8 0, i32 24, i32 8, i1 false)

  %5 = bitcast [11 x %jl_value_t*]* %1 to i64*

  %6 = bitcast %jl_value_t** %3 to i8*

  call void @llvm.memset.p0i8.i64(i8* %6, i8 0, i64 40, i32 8, i1 false)

  store i64 18, i64* %5, align 8

  %7 = bitcast %jl_value_t*** %0 to i64*

  %8 = load i64, i64* %7, align 8

  %9 = getelementptr [11 x %jl_value_t*], [11 x %jl_value_t*]* %1, i64 0, 
i64 1

  %10 = bitcast %jl_value_t** %9 to i64*

  store i64 %8, i64* %10, align 8

  store %jl_value_t** %.sub, %jl_value_t*** %0, align 8

  %"r#274" = alloca %UnitRange.6, align 8

  store %jl_value_t* inttoptr (i64 4400218208 to %jl_value_t*), 
%jl_value_t** %a, align 8

  %11 = getelementptr inbounds %UnitRange.6, %UnitRange.6* %"r#274", i64 0, 
i32 0

  store i64 1, i64* %11, align 8

  %12 = getelementptr inbounds %UnitRange.6, %UnitRange.6* %"r#274", i64 0, 
i32 1

  store i64 1000, i64* %12, align 8

  %13 = call i64 @julia_simd_inner_length_70896(%UnitRange.6* nonnull 
%"r#274", i64 0) #0

  %14 = icmp eq i64 %13, 0

  br i1 %14, label %L.backedge, label %if26.lr.ph


L8:                                               ; preds = %if26

  %15 = load %jl_value_t*, %jl_value_t** %a, align 8

  store %jl_value_t* %15, %jl_value_t** %40, align 8

  %16 = getelementptr inbounds %jl_value_t, %jl_value_t* %15, i64 -1, i32 0

  %17 = bitcast %jl_value_t** %16 to i64*

  %18 = load i64, i64* %17, align 8

  %19 = and i64 %18, -16

  %20 = inttoptr i64 %19 to %jl_value_t*

  %21 = icmp eq %jl_value_t* %20, inttoptr (i64 4400088496 to %jl_value_t*)

  br i1 %21, label %L11, label %L10


L10:                                              ; preds = %L8

  %22 = load i64, i64* %46, align 8

  store i64 %22, i64* %47, align 8

  %23 = and i64 %53, 3689348814741910323

  %24 = lshr i64 %53, 2

  %25 = and i64 %24, 3689348814741910323

  %26 = add nuw nsw i64 %25, %23

  store %jl_value_t* inttoptr (i64 4408276712 to %jl_value_t*), 
%jl_value_t** %2, align 8

  %27 = call %jl_value_t* @jl_box_uint64(i64 zeroext %26)

  store %jl_value_t* %27, %jl_value_t** %44, align 8

  %28 = call %jl_value_t* @jl_apply_generic(%jl_value_t** %2, i32 3)

  store %jl_value_t* %28, %jl_value_t** %41, align 8

  br label %L12


L11:                                              ; preds = %L8, %if26

  %"#temp#3.0" = phi %jl_value_t* [ inttoptr (i64 4409008592 to 
%jl_value_t*), %if26 ], [ inttoptr (i64 4423075536 to %jl_value_t*), %L8 ]

  store %jl_value_t* %"#temp#3.0", %jl_value_t** %42, align 8

  %29 = load i64, i64* %46, align 8

  store i64 %29, i64* %47, align 8

  %30 = and i64 %53, 3689348814741910323

  %31 = lshr i64 %53, 2

  %32 = and i64 %31, 3689348814741910323

  %33 = add nuw nsw i64 %32, %30

  store %jl_value_t* inttoptr (i64 4408276712 to %jl_value_t*), 
%jl_value_t** %2, align 8

  %34 = call %jl_value_t* @jl_box_uint64(i64 zeroext %33)

  store %jl_value_t* %34, %jl_value_t** %44, align 8

  %35 = call %jl_value_t* @jl_invoke(%jl_value_t* %"#temp#3.0", 
%jl_value_t** %2, i32 3)

  store %jl_value_t* %35, %jl_value_t** %43, align 8

  br label %L12


L12:                                              ; preds = %L11, %L10

  %storemerge.in.in = phi %jl_value_t* [ %28, %L10 ], [ %35, %L11 ]

  %storemerge.in = bitcast %jl_value_t* %storemerge.in.in to i64*

  %storemerge = load i64, i64* %storemerge.in, align 1

  %36 = call %jl_value_t* @jl_box_uint64(i64 zeroext %storemerge)

  store %jl_value_t* %36, %jl_value_t** %a, align 8

  %37 = add nuw i64 %"i#277.040", 1

  %exitcond = icmp eq i64 %37, %13

  br i1 %exitcond, label %L.backedge.loopexit, label %if26


L.backedge.loopexit:                              ; preds = %L12

  br label %L.backedge


L.backedge:                                       ; preds = 
%L.backedge.loopexit, %top

  %38 = load %jl_value_t*, %jl_value_t** %a, align 8

  %39 = load i64, i64* %10, align 8

  store i64 %39, i64* %7, align 8

  ret %jl_value_t* %38


if26.lr.ph:                                       ; preds = %top

  %40 = getelementptr [11 x %jl_value_t*], [11 x %jl_value_t*]* %1, i64 0, 
i64 3

  %41 = getelementptr [11 x %jl_value_t*], [11 x %jl_value_t*]* %1, i64 0, 
i64 4

  %42 = getelementptr [11 x %jl_value_t*], [11 x %jl_value_t*]* %1, i64 0, 
i64 5

  %43 = getelementptr [11 x %jl_value_t*], [11 x %jl_value_t*]* %1, i64 0, 
i64 6

  %44 = getelementptr [11 x %jl_value_t*], [11 x %jl_value_t*]* %1, i64 0, 
i64 10

  %45 = getelementptr [11 x %jl_value_t*], [11 x %jl_value_t*]* %1, i64 0, 
i64 9

  %46 = bitcast %jl_value_t** %a to i64*

  %47 = bitcast %jl_value_t** %45 to i64*

  %.pre = load %jl_value_t*, %jl_value_t** %a, align 8

  br label %if26


if26:                                             ; preds = %L12, 
%if26.lr.ph

  %48 = phi %jl_value_t* [ %.pre, %if26.lr.ph ], [ %36, %L12 ]

  %"i#277.040" = phi i64 [ 0, %if26.lr.ph ], [ %37, %L12 ]

  %49 = load i64, i64* %11, align 8

  %50 = add i64 %49, %"i#277.040"

  %51 = lshr i64 %50, 1

  %52 = and i64 %51, 6148914691236517205

  %53 = sub i64 %50, %52

  store %jl_value_t* %48, %jl_value_t** %3, align 8

  %54 = getelementptr inbounds %jl_value_t, %jl_value_t* %48, i64 -1, i32 0

  %55 = bitcast %jl_value_t** %54 to i64*

  %56 = load i64, i64* %55, align 8

  %57 = and i64 %56, -16

  %58 = inttoptr i64 %57 to %jl_value_t*

  %59 = icmp eq %jl_value_t* %58, inttoptr (i64 4400097136 to %jl_value_t*)

  br i1 %59, label %L11, label %L8

}



Thanks,
Ben.

Reply via email to