Source file src/cmd/compile/internal/ssarewrite/rewriteppc64latelower/ppc64latelower_helpers.go

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package rewriteppc64latelower
     6  
     7  import (
     8  	"cmd/compile/internal/ssa"
     9  	"cmd/compile/internal/ssa/ssaop"
    10  	"cmd/compile/internal/types"
    11  )
    12  
    13  // Convert a PPC64 opcode from the Op to OpCC form. This converts (op x y)
    14  // to (Select0 (opCC x y)) without having to explicitly fixup every user
    15  // of op.
    16  //
    17  // E.g consider the case:
    18  // a = (ADD x y)
    19  // b = (CMPconst [0] a)
    20  // c = (OR a z)
    21  //
    22  // A rule like (CMPconst [0] (ADD x y)) => (CMPconst [0] (Select0 (ADDCC x y)))
    23  // would produce:
    24  // a  = (ADD x y)
    25  // a' = (ADDCC x y)
    26  // a” = (Select0 a')
    27  // b  = (CMPconst [0] a”)
    28  // c  = (OR a z)
    29  //
    30  // which makes it impossible to rewrite the second user. Instead the result
    31  // of this conversion is:
    32  // a' = (ADDCC x y)
    33  // a  = (Select0 a')
    34  // b  = (CMPconst [0] a)
    35  // c  = (OR a z)
    36  //
    37  // Which makes it trivial to rewrite b using a lowering rule.
    38  func convertPPC64OpToOpCC(op *ssa.Value) *ssa.Value {
    39  	ccOpMap := map[ssaop.Op]ssaop.Op{
    40  		ssaop.OpPPC64ADD:      ssaop.OpPPC64ADDCC,
    41  		ssaop.OpPPC64ADDconst: ssaop.OpPPC64ADDCCconst,
    42  		ssaop.OpPPC64AND:      ssaop.OpPPC64ANDCC,
    43  		ssaop.OpPPC64ANDN:     ssaop.OpPPC64ANDNCC,
    44  		ssaop.OpPPC64ANDconst: ssaop.OpPPC64ANDCCconst,
    45  		ssaop.OpPPC64CNTLZD:   ssaop.OpPPC64CNTLZDCC,
    46  		ssaop.OpPPC64MULHDU:   ssaop.OpPPC64MULHDUCC,
    47  		ssaop.OpPPC64NEG:      ssaop.OpPPC64NEGCC,
    48  		ssaop.OpPPC64NOR:      ssaop.OpPPC64NORCC,
    49  		ssaop.OpPPC64OR:       ssaop.OpPPC64ORCC,
    50  		ssaop.OpPPC64RLDICL:   ssaop.OpPPC64RLDICLCC,
    51  		ssaop.OpPPC64SUB:      ssaop.OpPPC64SUBCC,
    52  		ssaop.OpPPC64XOR:      ssaop.OpPPC64XORCC,
    53  	}
    54  	b := op.Block
    55  	opCC := b.NewValue0I(op.Pos, ccOpMap[op.Op], types.NewTuple(op.Type, types.TypeFlags), op.AuxInt)
    56  	opCC.AddArgs(op.Args...)
    57  	op.Reset(ssaop.OpSelect0)
    58  	op.AddArgs(opCC)
    59  	return op
    60  }
    61  
    62  // Try converting a RLDICL to ANDCC. If successful, return the mask otherwise 0.
    63  func convertPPC64RldiclAndccconst(sauxint int64) int64 {
    64  	r, _, _, mask := ssa.DecodePPC64RotateMask(sauxint)
    65  	if r != 0 || mask&0xFFFF != mask {
    66  		return 0
    67  	}
    68  	return int64(mask)
    69  }
    70  
    71  // Merge (RLDICL [encoded] (SRDconst [s] x)) into (RLDICL [new_encoded] x)
    72  // SRDconst on PPC64 is an extended mnemonic of RLDICL. If the input to an
    73  // RLDICL is an SRDconst, and the RLDICL does not rotate its value, the two
    74  // operations can be combined. This functions assumes the two opcodes can
    75  // be merged, and returns an encoded rotate+mask value of the combined RLDICL.
    76  func mergePPC64RLDICLandSRDconst(encoded, s int64) int64 {
    77  	mb := s
    78  	r := 64 - s
    79  	// A larger mb is a smaller mask.
    80  	if (encoded>>8)&0xFF < mb {
    81  		encoded = (encoded &^ 0xFF00) | mb<<8
    82  	}
    83  	// The rotate is expected to be 0.
    84  	if (encoded & 0xFF0000) != 0 {
    85  		panic("non-zero rotate")
    86  	}
    87  	return encoded | r<<16
    88  }
    89  

View as plain text