| // 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 ( | |
| "cmd/compile/internal/types" | |
| "cmd/internal/src" | |
| "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 := c.Fun("entry", | |
| Bloc("entry", | |
| Valu("mem", OpInitMem, types.TypeMem, 0, nil), | |
| Valu("SP", OpSP, c.config.Types.Uintptr, 0, nil), | |
| Valu("ret", OpAddr, c.config.Types.Int64.PtrTo(), 0, nil, "SP"), | |
| Valu("N", OpArg, c.config.Types.Int64, 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Int64)), | |
| Valu("starti", OpConst64, c.config.Types.Int64, 0, nil), | |
| Valu("startsum", OpConst64, c.config.Types.Int64, 0, nil), | |
| Goto("b1")), | |
| Bloc("b1", | |
| Valu("phii", OpPhi, c.config.Types.Int64, 0, nil, "starti", "i"), | |
| Valu("phisum", OpPhi, c.config.Types.Int64, 0, nil, "startsum", "sum"), | |
| Valu("cmp1", OpLess64, c.config.Types.Bool, 0, nil, "phii", "N"), | |
| If("cmp1", "b2", "b3")), | |
| Bloc("b2", | |
| Valu("c1", OpConst64, c.config.Types.Int64, 1, nil), | |
| Valu("i", OpAdd64, c.config.Types.Int64, 0, nil, "phii", "c1"), | |
| Valu("c3", OpConst64, c.config.Types.Int64, 3, nil), | |
| Valu("sum", OpAdd64, c.config.Types.Int64, 0, nil, "phisum", "c3"), | |
| Goto("b1")), | |
| Bloc("b3", | |
| Valu("retdef", OpVarDef, types.TypeMem, 0, nil, "mem"), | |
| Valu("store", OpStore, types.TypeMem, 0, c.config.Types.Int64, "ret", "phisum", "retdef"), | |
| 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, | |
| }) | |
| } |