needsRegister returns true if the value requires a register.
(s *Step)
| 7 | "git.urbach.dev/cli/q/src/types" |
| 8 | ) |
| 9 | |
| 10 | // needsRegister returns true if the value requires a register. |
| 11 | func (f *Function) needsRegister(s *Step) bool { |
| 12 | typ := types.Unwrap(s.Value.Type()) |
| 13 | |
| 14 | if typ == types.Void { |
| 15 | return false |
| 16 | } |
| 17 | |
| 18 | _, isPhi := s.Value.(*ssa.Phi) |
| 19 | |
| 20 | if isPhi { |
| 21 | return true |
| 22 | } |
| 23 | |
| 24 | _, isStruct := typ.(*types.Struct) |
| 25 | |
| 26 | if isStruct { |
| 27 | return false |
| 28 | } |
| 29 | |
| 30 | _, isTuple := typ.(*types.Tuple) |
| 31 | |
| 32 | if isTuple { |
| 33 | return false |
| 34 | } |
| 35 | |
| 36 | users := s.Value.Users() |
| 37 | |
| 38 | if len(users) == 0 { |
| 39 | return false |
| 40 | } |
| 41 | |
| 42 | switch instr := s.Value.(type) { |
| 43 | case *ssa.BinaryOp: |
| 44 | if instr.Op.IsComparison() { |
| 45 | next := f.Steps[s.Index+1] |
| 46 | branch, isBranch := next.Value.(*ssa.Branch) |
| 47 | return !isBranch || !slices.Contains(branch.Inputs(), s.Value) |
| 48 | } |
| 49 | |
| 50 | return true |
| 51 | case *ssa.Cas: |
| 52 | return false |
| 53 | case *ssa.Int: |
| 54 | if len(users) == 1 { |
| 55 | // Check if we can encode single-use integers as immediates |
| 56 | // directly embedded in the instruction itself rather than |
| 57 | // requiring an extra register and a move. |
| 58 | return !f.canEncodeNumber(users[0], instr) |
| 59 | } |
| 60 | case *ssa.Memory: |
no test coverage detected