--- /dev/null
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import (
+ "testing"
+)
+
+func TestLoopConditionS390X(t *testing.T) {
+ // Test that a simple loop condition does not generate a conditional
+ // move (issue #19227).
+ //
+ // MOVDLT is generated when Less64 is lowered but should be
+ // optimized into an LT branch.
+ //
+ // For example, compiling the following loop:
+ //
+ // for i := 0; i < N; i++ {
+ // sum += 3
+ // }
+ //
+ // should generate assembly similar to:
+ // loop:
+ // CMP R0, R1
+ // BGE done
+ // ADD $3, R4
+ // ADD $1, R1
+ // BR loop
+ // done:
+ //
+ // rather than:
+ // loop:
+ // MOVD $0, R2
+ // MOVD $1, R3
+ // CMP R0, R1
+ // MOVDLT R2, R3
+ // CMPW R2, $0
+ // BNE done
+ // ADD $3, R4
+ // ADD $1, R1
+ // BR loop
+ // done:
+ //
+ c := testConfigS390X(t)
+ fun := Fun(c, "entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, TypeMem, 0, nil),
+ Valu("SP", OpSP, TypeUInt64, 0, nil),
+ Valu("Nptr", OpOffPtr, TypeInt64Ptr, 8, nil, "SP"),
+ Valu("ret", OpOffPtr, TypeInt64Ptr, 16, nil, "SP"),
+ Valu("N", OpLoad, TypeInt64, 0, nil, "Nptr", "mem"),
+ Valu("starti", OpConst64, TypeInt64, 0, nil),
+ Valu("startsum", OpConst64, TypeInt64, 0, nil),
+ Goto("b1")),
+ Bloc("b1",
+ Valu("phii", OpPhi, TypeInt64, 0, nil, "starti", "i"),
+ Valu("phisum", OpPhi, TypeInt64, 0, nil, "startsum", "sum"),
+ Valu("cmp1", OpLess64, TypeBool, 0, nil, "phii", "N"),
+ If("cmp1", "b2", "b3")),
+ Bloc("b2",
+ Valu("c1", OpConst64, TypeInt64, 1, nil),
+ Valu("i", OpAdd64, TypeInt64, 0, nil, "phii", "c1"),
+ Valu("c3", OpConst64, TypeInt64, 3, nil),
+ Valu("sum", OpAdd64, TypeInt64, 0, nil, "phisum", "c3"),
+ Goto("b1")),
+ Bloc("b3",
+ Valu("store", OpStore, TypeMem, 8, nil, "ret", "phisum", "mem"),
+ Exit("store")))
+ CheckFunc(fun.f)
+ Compile(fun.f)
+ CheckFunc(fun.f)
+
+ checkOpcodeCounts(t, fun.f, map[Op]int{
+ OpS390XMOVDLT: 0,
+ OpS390XMOVDGT: 0,
+ OpS390XMOVDLE: 0,
+ OpS390XMOVDGE: 0,
+ OpS390XMOVDEQ: 0,
+ OpS390XMOVDNE: 0,
+ OpS390XCMP: 1,
+ OpS390XCMPWconst: 0,
+ })
+
+ fun.f.Free()
+}