From 1658263bbfbf0c31f179df878049e6d4690501c8 Mon Sep 17 00:00:00 2001 From: Giovanni Bajo Date: Mon, 16 Sep 2019 10:25:48 +0200 Subject: cmd/compile: detect indvars that are bound by other indvars prove wasn't able to detect induction variables that was bound by another inducation variable. This happened because an indvar is a Phi, and thus in case of a dependency, the loop bounding condition looked as Phi < Phi. This triggered an existing codepath that checked whether the upper bound was a Phi to detect loop conditions written in reversed order respect to the idiomatic way (eg: for i:=0; len(n)>i; i++). To fix this, we call the indvar pattern matching on both operands of the loop condition, so that the first operand that matches will be treated as the indvar. Updates #24660 (removes a boundcheck from Fannkuch) Change-Id: Iade83d8deb54f14277ed3f2e37b190e1ed173d11 Reviewed-on: https://go-review.googlesource.com/c/go/+/195220 Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/loopbce.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'src/cmd/compile') diff --git a/src/cmd/compile/internal/ssa/loopbce.go b/src/cmd/compile/internal/ssa/loopbce.go index 2ce687822a..bfa2597493 100644 --- a/src/cmd/compile/internal/ssa/loopbce.go +++ b/src/cmd/compile/internal/ssa/loopbce.go @@ -111,17 +111,25 @@ func findIndVar(f *Func) []indVar { continue } - // See if the arguments are reversed (i < len() <=> len() > i) - less := true - if max.Op == OpPhi { - ind, max = max, ind - less = false - } - // See if this is really an induction variable + less := true min, inc, nxt := parseIndVar(ind) if min == nil { - continue + // We failed to parse the induction variable. Before punting, we want to check + // whether the control op was written with arguments in non-idiomatic order, + // so that we believe being "max" (the upper bound) is actually the induction + // variable itself. This would happen for code like: + // for i := 0; len(n) > i; i++ + min, inc, nxt = parseIndVar(max) + if min == nil { + // No recognied induction variable on either operand + continue + } + + // Ok, the arguments were reversed. Swap them, and remember that we're + // looking at a ind >/>= loop (so the induction must be decrementing). + ind, max = max, ind + less = false } // Expect the increment to be a nonzero constant. -- cgit v1.3