ConstantFoldingMIRBuilder.h revision 360784
1//===-- llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h  --*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements a version of MachineIRBuilder which does trivial
10/// constant folding.
11//===----------------------------------------------------------------------===//
12#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
13#include "llvm/CodeGen/GlobalISel/Utils.h"
14
15namespace llvm {
16
17/// An MIRBuilder which does trivial constant folding of binary ops.
18/// Calls to buildInstr will also try to constant fold binary ops.
19class ConstantFoldingMIRBuilder : public MachineIRBuilder {
20public:
21  // Pull in base class constructors.
22  using MachineIRBuilder::MachineIRBuilder;
23
24  virtual ~ConstantFoldingMIRBuilder() = default;
25
26  // Try to provide an overload for buildInstr for binary ops in order to
27  // constant fold.
28  MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps,
29                                 ArrayRef<SrcOp> SrcOps,
30                                 Optional<unsigned> Flags = None) override {
31    switch (Opc) {
32    default:
33      break;
34    case TargetOpcode::G_ADD:
35    case TargetOpcode::G_AND:
36    case TargetOpcode::G_ASHR:
37    case TargetOpcode::G_LSHR:
38    case TargetOpcode::G_MUL:
39    case TargetOpcode::G_OR:
40    case TargetOpcode::G_SHL:
41    case TargetOpcode::G_SUB:
42    case TargetOpcode::G_XOR:
43    case TargetOpcode::G_UDIV:
44    case TargetOpcode::G_SDIV:
45    case TargetOpcode::G_UREM:
46    case TargetOpcode::G_SREM: {
47      assert(DstOps.size() == 1 && "Invalid dst ops");
48      assert(SrcOps.size() == 2 && "Invalid src ops");
49      const DstOp &Dst = DstOps[0];
50      const SrcOp &Src0 = SrcOps[0];
51      const SrcOp &Src1 = SrcOps[1];
52      if (auto MaybeCst =
53              ConstantFoldBinOp(Opc, Src0.getReg(), Src1.getReg(), *getMRI()))
54        return buildConstant(Dst, MaybeCst->getSExtValue());
55      break;
56    }
57    case TargetOpcode::G_SEXT_INREG: {
58      assert(DstOps.size() == 1 && "Invalid dst ops");
59      assert(SrcOps.size() == 2 && "Invalid src ops");
60      const DstOp &Dst = DstOps[0];
61      const SrcOp &Src0 = SrcOps[0];
62      const SrcOp &Src1 = SrcOps[1];
63      if (auto MaybeCst =
64              ConstantFoldExtOp(Opc, Src0.getReg(), Src1.getImm(), *getMRI()))
65        return buildConstant(Dst, MaybeCst->getSExtValue());
66      break;
67    }
68    }
69    return MachineIRBuilder::buildInstr(Opc, DstOps, SrcOps);
70  }
71};
72} // namespace llvm
73