aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/Target/RISCV/RISCVMachineCombiner.cpp
blob: f41e77a86171bcd77b4814dc0f268c48424c6c4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// SPDX-License-Identifier: GPL-3.0-or-later

#include "RISCV.h"
#include "rcc/Target/RISCV/RISCVTarget.h"

#include <cstdint>
#include <cstdlib>
#include <string>
#include <utility>
#include <vector>

namespace rcc::riscv {
namespace {

[[nodiscard]] constexpr Opcode targetOpcode(InstructionOpcode Value) noexcept {
  return Opcode::fromValue(static_cast<std::uint32_t>(Value));
}

[[nodiscard]] constexpr MachineCombinerStageMask allOptimizationStages() noexcept {
  return machineCombinerStageMask(MachineCombinerStage::SelectedSSA) |
         machineCombinerStageMask(MachineCombinerStage::PreRegisterAllocation) |
         machineCombinerStageMask(MachineCombinerStage::PostRegisterAllocation) |
         machineCombinerStageMask(MachineCombinerStage::PostFrame);
}

[[nodiscard]] MachineCombinerPattern immediateIdentity(InstructionOpcode OpcodeValue,
                                                       std::string Name, std::int64_t Immediate) {
  return {
      .Name = std::move(Name),
      .RootOpcode = targetOpcode(OpcodeValue),
      .Stages = allOptimizationStages(),
      .Predicates = {{MachineCombinerPredicateKind::ImmediateEquals, 2, 0, Immediate}},
      .Action = {MachineCombinerActionKind::ReplaceDefWithOperandAndErase, 0, 1},
  };
}

[[nodiscard]] MachineCombinerPattern zeroRegisterIdentity(InstructionOpcode OpcodeValue,
                                                          std::string Name, std::size_t ZeroOperand,
                                                          std::size_t SourceOperand) {
  return {
      .Name = std::move(Name),
      .RootOpcode = targetOpcode(OpcodeValue),
      .Stages = allOptimizationStages(),
      .Predicates = {{MachineCombinerPredicateKind::PhysicalRegisterEquals, ZeroOperand, 0,
                      static_cast<std::int64_t>(PhysicalRegisterID::X0)}},
      .Action = {MachineCombinerActionKind::ReplaceDefWithOperandAndErase, 0, SourceOperand},
  };
}

[[nodiscard]] MachineCombinerPattern equalSourceIdentity(InstructionOpcode OpcodeValue,
                                                         std::string Name) {
  return {
      .Name = std::move(Name),
      .RootOpcode = targetOpcode(OpcodeValue),
      .Stages = allOptimizationStages(),
      .Predicates = {{MachineCombinerPredicateKind::RegisterEquals, 1, 2, 0}},
      .Action = {MachineCombinerActionKind::ReplaceDefWithOperandAndErase, 0, 1},
  };
}

[[nodiscard]] std::vector<MachineCombinerPattern> createPatterns() {
  std::vector<MachineCombinerPattern> Patterns;
  Patterns.push_back(immediateIdentity(InstructionOpcode::ADDI, "addi-zero", 0));
  Patterns.push_back(immediateIdentity(InstructionOpcode::XORI, "xori-zero", 0));
  Patterns.push_back(immediateIdentity(InstructionOpcode::ORI, "ori-zero", 0));
  Patterns.push_back(immediateIdentity(InstructionOpcode::ANDI, "andi-all-ones", -1));
  Patterns.push_back(immediateIdentity(InstructionOpcode::SLLI, "slli-zero", 0));
  Patterns.push_back(immediateIdentity(InstructionOpcode::SRLI, "srli-zero", 0));
  Patterns.push_back(immediateIdentity(InstructionOpcode::SRAI, "srai-zero", 0));
  Patterns.push_back(zeroRegisterIdentity(InstructionOpcode::ADD, "add-zero-right", 2, 1));
  Patterns.push_back(zeroRegisterIdentity(InstructionOpcode::ADD, "add-zero-left", 1, 2));
  Patterns.push_back(zeroRegisterIdentity(InstructionOpcode::OR, "or-zero-right", 2, 1));
  Patterns.push_back(zeroRegisterIdentity(InstructionOpcode::OR, "or-zero-left", 1, 2));
  Patterns.push_back(zeroRegisterIdentity(InstructionOpcode::XOR, "xor-zero-right", 2, 1));
  Patterns.push_back(zeroRegisterIdentity(InstructionOpcode::XOR, "xor-zero-left", 1, 2));
  Patterns.push_back(zeroRegisterIdentity(InstructionOpcode::SUB, "sub-zero-right", 2, 1));
  Patterns.push_back(equalSourceIdentity(InstructionOpcode::FSGNJ_S, "fsgnj-s-copy"));
  Patterns.push_back(equalSourceIdentity(InstructionOpcode::FSGNJ_D, "fsgnj-d-copy"));
  return Patterns;
}

} // namespace

const TargetMachineCombinerInfo &machineCombinerInfo() noexcept {
  static const Expected<TargetMachineCombinerInfo> Info =
      TargetMachineCombinerInfo::create(createPatterns());
  if (!Info)
    std::abort();
  return *Info;
}

} // namespace rcc::riscv