[PATCH] [llgo] irgen: fix canAvoid*

Andrew Wilkins axwalk at gmail.com
Tue Dec 16 17:38:52 PST 2014


http://reviews.llvm.org/D6676

Files:
  irgen/ssa.go
  test/irgen/avoidload.go

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,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: 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]]

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D6676.17376.patch
Type: text/x-patch
Size: 3053 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141217/d77a43e4/attachment.bin>


More information about the llvm-commits mailing list