Index: irgen/ssa.go =================================================================== --- irgen/ssa.go +++ irgen/ssa.go @@ -663,7 +663,7 @@ return value } - panic("Instruction not visited yet") + panic(fmt.Errorf("Instruction %q not visited yet", v.Name())) } func (fr *frame) llvmvalue(v ssa.Value) llvm.Value { @@ -696,11 +696,14 @@ } } -func (fr *frame) canAvoidElementLoad(refs []ssa.Instruction) bool { - for _, ref := range refs { - switch ref.(type) { - case *ssa.Field, *ssa.Index: - // ok +func (fr *frame) canAvoidElementLoad(ptr ssa.Value) bool { + for _, ref := range *ptr.Referrers() { + switch ref := ref.(type) { + case *ssa.Field: + case *ssa.Index: + if ref.X != ptr { + return false + } default: return false } @@ -724,11 +727,14 @@ // We only know how to avoid loads if they are used to create an interface // or read an element of the structure. If we see any other referrer, abort. for _, ref := range *instr.Referrers() { - switch ref.(type) { + switch ref := ref.(type) { case *ssa.MakeInterface: esc = true - case *ssa.Field, *ssa.Index: - // ok + case *ssa.Field: + case *ssa.Index: + if ref.X != instr { + return false + } default: return false } @@ -895,7 +901,7 @@ fieldtyp := instr.Type() if p, ok := fr.ptr[instr.X]; ok { field := fr.builder.CreateStructGEP(p, instr.Field, instr.Name()) - if fr.canAvoidElementLoad(*instr.Referrers()) { + if fr.canAvoidElementLoad(instr) { fr.ptr[instr] = field } else { fr.env[instr] = newValue(fr.builder.CreateLoad(field, ""), fieldtyp) @@ -959,7 +965,7 @@ fr.condBrRuntimeError(cond, gccgoRuntimeErrorARRAY_INDEX_OUT_OF_BOUNDS) addr := fr.builder.CreateGEP(arrayptr, []llvm.Value{zero, index}, "") - if fr.canAvoidElementLoad(*instr.Referrers()) { + if fr.canAvoidElementLoad(instr) { fr.ptr[instr] = addr } else { fr.env[instr] = newValue(fr.builder.CreateLoad(addr, ""), instr.Type()) Index: test/irgen/avoidload.go =================================================================== --- /dev/null +++ test/irgen/avoidload.go @@ -0,0 +1,15 @@ +// RUN: llgo -S -emit-llvm -o - %s | FileCheck %s + +package foo + +type X struct { + indices [1]int +} + +// CHECK-NOT: load [200 x i64] +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}, i64 160000, i32 1, i1 false) +var _ = [100][200]int{}[0][0] + +// CHECK-NOT: load [1024 x i64] +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}, i64 8192, i32 1, i1 false) +var _ = [1024]int{}[X{}.indices[0]]