[PATCH] [llgo] irgen: fix canAvoid*
Peter Collingbourne
peter at pcc.me.uk
Wed Dec 17 01:46:01 PST 2014
REPOSITORY
rL LLVM
http://reviews.llvm.org/D6676
Files:
llgo/trunk/irgen/ssa.go
llgo/trunk/test/irgen/avoidload.go
Index: llgo/trunk/irgen/ssa.go
===================================================================
--- llgo/trunk/irgen/ssa.go
+++ llgo/trunk/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,10 +696,14 @@
}
}
-func (fr *frame) canAvoidElementLoad(refs []ssa.Instruction) bool {
- for _, ref := range refs {
- switch ref.(type) {
- case *ssa.Field, *ssa.Index:
+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
+ }
// ok
default:
return false
@@ -712,7 +716,7 @@
// If this value is sufficiently large, look through referrers to see if we can
// avoid a load.
func (fr *frame) canAvoidLoad(instr *ssa.UnOp, op llvm.Value) bool {
- if fr.types.Sizeof(instr.Type()) < 16 {
+ if fr.types.Sizeof(instr.Type()) < 2*fr.types.Sizeof(types.Typ[types.Int]) {
// Don't bother with small values.
return false
}
@@ -724,10 +728,16 @@
// 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:
+ case *ssa.Field:
+ case *ssa.Index:
+ if ref.X != instr {
+ // This should never happen, as indices are always of type int
+ // and we don't bother with values smaller than 2*sizeof(int).
+ panic("impossible")
+ }
// ok
default:
return false
@@ -895,7 +905,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 +969,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: llgo/trunk/test/irgen/avoidload.go
===================================================================
--- llgo/trunk/test/irgen/avoidload.go
+++ llgo/trunk/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]]
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D6676.17380.patch
Type: text/x-patch
Size: 3133 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141217/7005c11d/attachment.bin>
More information about the llvm-commits
mailing list