llir-opt  0.0.1
Low-Level Post-Link Optimiser for OCaml and C
constraints.h
1 // This file if part of the llir-opt project.
2 // Licensing information can be found in the LICENSE file.
3 // (C) 2018 Nandor Licker. All rights reserved.
4 
5 #pragma once
6 
7 #include <unordered_set>
8 
9 #include "core/adt/id.h"
10 #include "core/adt/bitset.h"
11 #include "core/adt/union_find.h"
12 #include "core/target.h"
13 #include "core/inst_visitor.h"
14 #include "passes/tags/tagged_type.h"
15 #include "passes/tags/constraint_type.h"
16 
17 
18 
19 namespace tags {
20 
21 class RegisterAnalysis;
22 
23 
27 class ConstraintSolver : private InstVisitor<void> {
28 public:
30  RegisterAnalysis &analysis,
31  const Target *target,
32  bool banPolymorphism,
33  Prog &prog
34  );
35 
36  void Solve();
37 
38 private:
39  void BuildConstraints();
40  void CollapseEquivalences();
41  void SolveConstraints();
42  void RewriteTypes();
43 
44 private:
45  void VisitArgInst(ArgInst &i) override;
46  void VisitCallSite(CallSite &i) override;
47  void VisitLandingPadInst(LandingPadInst &i) override;
48 
49  void VisitSubInst(SubInst &i) override;
50  void VisitAddInst(AddInst &i) override;
51  void VisitAndInst(AndInst &i) override;
52  void VisitOrInst(OrInst &i) override;
53  void VisitXorInst(XorInst &i) override;
54  void VisitCmpInst(CmpInst &i) override;
55  void VisitSelectInst(SelectInst &i) override;
56  void VisitPhiInst(PhiInst &i) override;
57 
58  void VisitMovInst(MovInst &i) override;
59  void VisitExtensionInst(ExtensionInst &i) override;
60  void VisitTruncInst(TruncInst &i) override;
61  void VisitMemoryStoreInst(MemoryStoreInst &store) override;
62  void VisitMemoryLoadInst(MemoryLoadInst &load) override;
63  void VisitMemoryExchangeInst(MemoryExchangeInst &i) override;
64  void VisitMemoryCompareExchangeInst(MemoryCompareExchangeInst &i) override;
65 
66  void VisitFrameInst(FrameInst &i) override { ExactlyPointer(i); }
67  void VisitUndefInst(UndefInst &i) override;
68  void VisitAllocaInst(AllocaInst &i) override { ExactlyPointer(i); }
69  void VisitFloatInst(FloatInst &i) override { ExactlyInt(i); }
70  void VisitShiftRightInst(ShiftRightInst &i) override { ExactlyInt(i); }
71  void VisitSllInst(SllInst &i) override { ExactlyInt(i); }
72  void VisitRotateInst(RotateInst &i) override { ExactlyInt(i); }
73  void VisitCopySignInst(CopySignInst &i) override { ExactlyInt(i); }
74  void VisitGetInst(GetInst &i) override;
75  void VisitX86_RdTscInst(X86_RdTscInst &i) override { ExactlyInt(i); }
76  void VisitMultiplyInst(MultiplyInst &i) override { ExactlyInt(i); }
77  void VisitDivisionRemainderInst(DivisionRemainderInst &i) override { ExactlyInt(i); }
78  void VisitByteSwapInst(ByteSwapInst &i) override { ExactlyInt(i); }
79  void VisitBitCountInst(BitCountInst &i) override { ExactlyInt(i); }
80  void VisitBitCastInst(BitCastInst &i) override { Infer(i); }
81  void VisitVaStartInst(VaStartInst &i) override { ExactlyPointer(i.GetVAList()); }
82  void VisitX86_FPUControlInst(X86_FPUControlInst &i) override { AnyPointer(i.GetAddr()); }
83  void VisitSyscallInst(SyscallInst &i) override;
84  void VisitCloneInst(CloneInst &i) override { ExactlyInt(i); }
85  void VisitTerminatorInst(TerminatorInst &i) override {}
86  void VisitSetInst(SetInst &i) override {}
87  void VisitX86_OutInst(X86_OutInst &i) override {}
88  void VisitX86_WrMsrInst(X86_WrMsrInst &i) override {}
89  void VisitX86_LidtInst(X86_LidtInst &i) override {}
90  void VisitX86_LgdtInst(X86_LgdtInst &i) override {}
91  void VisitX86_LtrInst(X86_LtrInst &i) override {}
92  void VisitX86_HltInst(X86_HltInst &i) override {}
93  void VisitX86_PauseInst(X86_PauseInst &i) override {}
94  void VisitX86_YieldInst(X86_YieldInst &i) override {}
95  void VisitX86_BarrierInst(X86_BarrierInst &i) override {}
96  void VisitX86_FnClExInst(X86_FnClExInst &i) override {}
97 
98  void VisitInst(Inst &i) override;
99 
100 private:
102  struct Conj;
103 
105  struct Constraint {
106  ID<Constraint> Id;
107  ConstraintType Min;
108  ConstraintType Max;
109  BitSet<Constraint> Subset;
110  std::unordered_set<Ref<Inst>> Defs;
111 
112  Constraint(ID<Constraint> id, Ref<Inst> def)
113  : Id(id)
114  , Min(ConstraintType::BOT)
115  , Max(ConstraintType::PTR_INT)
116  {
117  Defs.insert(def);
118  }
119 
120  void Union(Constraint &that);
121 
122  void dump(llvm::raw_ostream &os = llvm::errs());
123  };
124 
125  ID<Constraint> Find(Ref<Inst> a);
126  Constraint *Map(Ref<Inst> a);
127 
128 private:
130  using Lit = std::tuple<ID<Constraint>, bool, bool>;
131 
132  static Lit IsInt(ID<Constraint> id) { return { id, false, true }; }
133  static Lit IsPtr(ID<Constraint> id) { return { id, true, true }; }
134  static Lit NotInt(ID<Constraint> id) { return { id, false, false }; }
135  static Lit NotPtr(ID<Constraint> id) { return { id, true, false }; }
136 
137  static Lit Conj(const Lit &l)
138  {
139  return { std::get<0>(l), std::get<1>(l), !std::get<2>(l) };
140  }
141 
143  struct Alternative {
144  Lit Disc;
145  llvm::SmallVector<Lit, 2> Conj;
146  };
147 
149  void Alternatives(Ref<Inst> i, llvm::ArrayRef<Alternative> alternatives);
150 
151 private:
152  void Subset(Ref<Inst> from, Ref<Inst> to);
153  void AtMost(Ref<Inst> a, ConstraintType type);
154  void AtLeast(Ref<Inst> a, ConstraintType type);
155 
156  void AtMostPointer(Ref<Inst> arg) { AtMost(arg, ConstraintType::PTR); }
157  void ExactlyPointer(Ref<Inst> arg) { Exactly(arg, ConstraintType::PTR); }
158  void ExactlyYoung(Ref<Inst> arg) { Exactly(arg, ConstraintType::YOUNG); }
159  void ExactlyHeap(Ref<Inst> arg) { Exactly(arg, ConstraintType::HEAP); }
160  void ExactlyInt(Ref<Inst> arg) { Exactly(arg, ConstraintType::INT); }
161  void ExactlyFunc(Ref<Inst> arg) { Exactly(arg, ConstraintType::FUNC); }
162 
163  void AnyPointer(Ref<Inst> a)
164  {
165  AtLeast(a, ConstraintType::PTR_BOT);
166  AtMost(a, ConstraintType::PTR);
167  }
168 
169  void Exactly(Ref<Inst> a, const ConstraintType &type)
170  {
171  AtMost(a, type);
172  AtLeast(a, type);
173  }
174 
175  void Equal(Ref<Inst> a, Ref<Inst> b)
176  {
177  Subset(a, b);
178  Subset(b, a);
179  }
180 
181  ConstraintType LowerBound(Type ty, TaggedType type);
182  ConstraintType UpperBound(Type ty, TaggedType type);
183 
184  void AtLeastInfer(Ref<Inst> arg, TaggedType type)
185  {
186  return AtLeast(arg, LowerBound(arg.GetType(), type));
187  }
188 
189  void AtMostInfer(Ref<Inst> arg, TaggedType type)
190  {
191  return AtMost(arg, UpperBound(arg.GetType(), type));
192  }
193 
194  void Infer(Ref<Inst> arg);
195 
196 private:
197  bool IsExtern(const Func &f);
198 
199 private:
201  RegisterAnalysis &analysis_;
203  const Target *target_;
205  bool banPolymorphism_;
207  Prog &prog_;
208 
210  std::unordered_map<Ref<Inst>, ID<Constraint>> ids_;
212  UnionFind<Constraint> union_;
214  std::unordered_map<const Func *, bool> externs_;
216  std::vector<llvm::SmallVector<Lit, 3>> conj_;
217 };
218 
219 }
220 
Inst
Definition: inst.h:53
Func
Definition: func.h:30
Target
Definition: target.h:24
ID< Constraint >
MovInst
Definition: mov.h:17
BitSet< Constraint >
tags::RegisterAnalysis
Definition: register_analysis.h:37
Prog
Definition: prog.h:33
tags::ConstraintSolver
Definition: constraints.h:27
InstVisitor
Definition: inst_visitor.h:15
Ref
Definition: ref.h:63
tags::TaggedType
Definition: tagged_type.h:17
UnionFind< Constraint >
PhiInst
Definition: phi.h:14