Skip to content

Commit 4739419

Browse files
pmurpull[bot]
authored andcommitted
cmd/compile: merge zero constant ISEL in PPC64 lateLower pass
Add a new SSA opcode ISELZ, similar to ISELB to represent a select of value or 0. Then, merge candidate ISEL opcodes inside the late lower pass. This avoids complicating rules within the the lower pass. Change-Id: I3b14c94b763863aadc834b0e910a85870c131313 Reviewed-on: https://go-review.googlesource.com/c/go/+/442596 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Lynn Boger <[email protected]> Reviewed-by: Michael Knyszek <[email protected]> Run-TryBot: Paul Murphy <[email protected]> Reviewed-by: Joedian Reid <[email protected]>
1 parent 981e9d4 commit 4739419

File tree

6 files changed

+102
-14
lines changed

6 files changed

+102
-14
lines changed

src/cmd/compile/internal/ppc64/ssa.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -963,18 +963,21 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
963963
p.To.Type = obj.TYPE_MEM
964964
p.To.Reg = v.Args[0].Reg()
965965

966-
case ssa.OpPPC64ISEL, ssa.OpPPC64ISELB:
967-
// ISEL, ISELB
968-
// AuxInt value indicates condition: 0=LT 1=GT 2=EQ 4=GE 5=LE 6=NE
969-
// ISEL only accepts 0, 1, 2 condition values but the others can be
970-
// achieved by swapping operand order.
971-
// arg0 ? arg1 : arg2 with conditions LT, GT, EQ
972-
// arg0 ? arg2 : arg1 for conditions GE, LE, NE
973-
// ISELB is used when a boolean result is needed, returning 0 or 1
966+
case ssa.OpPPC64ISEL, ssa.OpPPC64ISELB, ssa.OpPPC64ISELZ:
967+
// ISEL AuxInt ? arg0 : arg1
968+
// ISELB is a special case of ISEL where AuxInt ? $1 (arg0) : $0.
969+
// ISELZ is a special case of ISEL where arg1 is implicitly $0.
970+
//
971+
// AuxInt value indicates conditions 0=LT 1=GT 2=EQ 3=SO 4=GE 5=LE 6=NE 7=NSO.
972+
// ISEL accepts a CR bit argument, not a condition as expressed by AuxInt.
973+
// Convert the condition to a CR bit argument by the following conversion:
974+
//
975+
// AuxInt&3 ? arg0 : arg1 for conditions LT, GT, EQ, SO
976+
// AuxInt&3 ? arg1 : arg0 for conditions GE, LE, NE, NSO
974977
p := s.Prog(ppc64.AISEL)
975978
p.To.Type = obj.TYPE_REG
976979
p.To.Reg = v.Reg()
977-
// For ISELB, boolean result 0 or 1. Use R0 for 0 operand to avoid load.
980+
// For ISELB/ISELZ Use R0 for 0 operand to avoid load.
978981
r := obj.Addr{Type: obj.TYPE_REG, Reg: ppc64.REG_R0}
979982
if v.Op == ssa.OpPPC64ISEL {
980983
r.Reg = v.Args[1].Reg()

src/cmd/compile/internal/ssa/_gen/PPC64Ops.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -404,11 +404,14 @@ func init() {
404404
{name: "CMPWconst", argLength: 1, reg: gp1cr, asm: "CMPW", aux: "Int32", typ: "Flags"},
405405
{name: "CMPWUconst", argLength: 1, reg: gp1cr, asm: "CMPWU", aux: "Int32", typ: "Flags"},
406406

407-
// ISEL auxInt values 0=LT 1=GT 2=EQ arg2 ? arg0 : arg1
408-
// ISEL auxInt values 4=GE 5=LE 6=NE !arg2 ? arg1 : arg0
409-
// ISELB special case where arg0, arg1 values are 0, 1 for boolean result
410-
{name: "ISEL", argLength: 3, reg: crgp21, asm: "ISEL", aux: "Int32", typ: "Int32"}, // see above
411-
{name: "ISELB", argLength: 2, reg: crgp11, asm: "ISEL", aux: "Int32", typ: "Int32"}, // see above
407+
// ISEL arg2 ? arg0 : arg1
408+
// ISELB arg1 ? arg0 : $0. arg0 is some register holding $1.
409+
// ISELZ arg1 ? arg0 : $0
410+
// auxInt values 0=LT 1=GT 2=EQ 3=SO (summary overflow/unordered) 4=GE 5=LE 6=NE 7=NSO (not summary overflow/not unordered)
411+
// Note, auxInt^4 inverts the comparison condition. For example, LT^4 becomes GE, and "ISEL [a] x y z" is equivalent to ISEL [a^4] y x z".
412+
{name: "ISEL", argLength: 3, reg: crgp21, asm: "ISEL", aux: "Int32", typ: "Int32"},
413+
{name: "ISELB", argLength: 2, reg: crgp11, asm: "ISEL", aux: "Int32", typ: "Int32"},
414+
{name: "ISELZ", argLength: 2, reg: crgp11, asm: "ISEL", aux: "Int32"},
412415

413416
// pseudo-ops
414417
{name: "Equal", argLength: 1, reg: crgp}, // bool, true flags encode x==y false otherwise.

src/cmd/compile/internal/ssa/_gen/PPC64latelower.rules

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,8 @@
33
// license that can be found in the LICENSE file.
44

55
// This file contains rules used by the laterLower pass.
6+
7+
// Simplify ISEL x $0 z into ISELZ
8+
(ISEL [a] x (MOVDconst [0]) z) => (ISELZ [a] x z)
9+
// Simplify ISEL $0 y z into ISELZ by inverting comparison and reversing arguments.
10+
(ISEL [a] (MOVDconst [0]) y z) => (ISELZ [a^0x4] y z)

src/cmd/compile/internal/ssa/opGen.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cmd/compile/internal/ssa/rewritePPC64latelower.go

Lines changed: 38 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/codegen/condmove.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,3 +440,27 @@ func cmovzero2(c bool) int {
440440
// loong64:"MASKNEZ", -"MASKEQZ"
441441
return x
442442
}
443+
444+
// Conditionally selecting between a value or 0 can be done without
445+
// an extra load of 0 to a register on PPC64 by using R0 (which always
446+
// holds the value $0) instead. Verify both cases where either arg1
447+
// or arg2 is zero.
448+
func cmovzeroreg0(a, b int) int {
449+
x := 0
450+
if a == b {
451+
x = a
452+
}
453+
// ppc64:"ISEL\t[$]2, R[0-9]+, R0, R[0-9]+"
454+
// ppc64le:"ISEL\t[$]2, R[0-9]+, R0, R[0-9]+"
455+
return x
456+
}
457+
458+
func cmovzeroreg1(a, b int) int {
459+
x := a
460+
if a == b {
461+
x = 0
462+
}
463+
// ppc64:"ISEL\t[$]2, R0, R[0-9]+, R[0-9]+"
464+
// ppc64le:"ISEL\t[$]2, R0, R[0-9]+, R[0-9]+"
465+
return x
466+
}

0 commit comments

Comments
 (0)