To perform address arithmetic with arbitrary, non-constant indices, you need to use the getelementptr instruction, which is created using the CreateGEP function.
Note that getelementptr needs its argument to be a pointer, so you'll want to directly use the global variable or alloca that holds the array, rather than reading it first. This also means that you need a zero as the first index to follow the pointer. So all in all, the generated code to read array[i] should look something like this:
@array = global [3 x i32] [1,2,3]
define void f() {
%i = ; calculuate the index here
%array_i_ptr = getelementptr [3 x i32], [3 x i32]* @array, i32 0, i32 %i
%array_i_value = load i32, i32* array_i_ptr
; do something with %array_i_value
ret
}
Here I assumed array was a global variable. For a local variable, you'd use alloca instead. For a dynamically allocated array, you'd have a call to malloc, no array types and a getelementptr instruction with only one index (because we'd be working with a pointer to int, rather than pointer to array to int, so the zero index isn't necessary).