Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 1 | //===- subzero/src/IceTargetLowering.cpp - Basic lowering implementation --===// |
| 2 | // |
| 3 | // The Subzero Code Generator |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file implements the skeleton of the TargetLowering class, |
| 11 | // specifically invoking the appropriate lowering method for a given |
| 12 | // instruction kind and driving global register allocation. It also |
| 13 | // implements the non-deleted instruction iteration in |
| 14 | // LoweringContext. |
| 15 | // |
| 16 | //===----------------------------------------------------------------------===// |
| 17 | |
| 18 | #include "IceCfg.h" // setError() |
| 19 | #include "IceCfgNode.h" |
| 20 | #include "IceOperand.h" |
Jim Stichnoth | d97c7df | 2014-06-04 11:57:08 -0700 | [diff] [blame] | 21 | #include "IceRegAlloc.h" |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 22 | #include "IceTargetLowering.h" |
| 23 | #include "IceTargetLoweringX8632.h" |
| 24 | |
| 25 | namespace Ice { |
| 26 | |
| 27 | void LoweringContext::init(CfgNode *N) { |
| 28 | Node = N; |
| 29 | Cur = getNode()->getInsts().begin(); |
| 30 | End = getNode()->getInsts().end(); |
| 31 | skipDeleted(Cur); |
| 32 | Next = Cur; |
| 33 | advance(Next); |
| 34 | } |
| 35 | |
| 36 | void LoweringContext::insert(Inst *Inst) { |
| 37 | getNode()->getInsts().insert(Next, Inst); |
| 38 | Inst->updateVars(getNode()); |
| 39 | } |
| 40 | |
| 41 | void LoweringContext::skipDeleted(InstList::iterator &I) { |
| 42 | while (I != End && (*I)->isDeleted()) |
| 43 | ++I; |
| 44 | } |
| 45 | |
| 46 | void LoweringContext::advance(InstList::iterator &I) { |
| 47 | if (I != End) { |
| 48 | ++I; |
| 49 | skipDeleted(I); |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | TargetLowering *TargetLowering::createLowering(TargetArch Target, Cfg *Func) { |
| 54 | // These statements can be #ifdef'd to specialize the code generator |
| 55 | // to a subset of the available targets. TODO: use CRTP. |
| 56 | if (Target == Target_X8632) |
| 57 | return TargetX8632::create(Func); |
| 58 | #if 0 |
| 59 | if (Target == Target_X8664) |
| 60 | return IceTargetX8664::create(Func); |
| 61 | if (Target == Target_ARM32) |
| 62 | return IceTargetARM32::create(Func); |
| 63 | if (Target == Target_ARM64) |
| 64 | return IceTargetARM64::create(Func); |
| 65 | #endif |
| 66 | Func->setError("Unsupported target"); |
| 67 | return NULL; |
| 68 | } |
| 69 | |
Jim Stichnoth | d97c7df | 2014-06-04 11:57:08 -0700 | [diff] [blame] | 70 | void TargetLowering::doAddressOpt() { |
| 71 | if (llvm::isa<InstLoad>(*Context.getCur())) |
| 72 | doAddressOptLoad(); |
| 73 | else if (llvm::isa<InstStore>(*Context.getCur())) |
| 74 | doAddressOptStore(); |
| 75 | Context.advanceCur(); |
| 76 | Context.advanceNext(); |
| 77 | } |
| 78 | |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 79 | // Lowers a single instruction according to the information in |
| 80 | // Context, by checking the Context.Cur instruction kind and calling |
| 81 | // the appropriate lowering method. The lowering method should insert |
| 82 | // target instructions at the Cur.Next insertion point, and should not |
| 83 | // delete the Context.Cur instruction or advance Context.Cur. |
| 84 | // |
| 85 | // The lowering method may look ahead in the instruction stream as |
| 86 | // desired, and lower additional instructions in conjunction with the |
| 87 | // current one, for example fusing a compare and branch. If it does, |
| 88 | // it should advance Context.Cur to point to the next non-deleted |
| 89 | // instruction to process, and it should delete any additional |
| 90 | // instructions it consumes. |
| 91 | void TargetLowering::lower() { |
| 92 | assert(!Context.atEnd()); |
| 93 | Inst *Inst = *Context.getCur(); |
| 94 | switch (Inst->getKind()) { |
| 95 | case Inst::Alloca: |
| 96 | lowerAlloca(llvm::dyn_cast<InstAlloca>(Inst)); |
| 97 | break; |
| 98 | case Inst::Arithmetic: |
| 99 | lowerArithmetic(llvm::dyn_cast<InstArithmetic>(Inst)); |
| 100 | break; |
| 101 | case Inst::Assign: |
| 102 | lowerAssign(llvm::dyn_cast<InstAssign>(Inst)); |
| 103 | break; |
| 104 | case Inst::Br: |
| 105 | lowerBr(llvm::dyn_cast<InstBr>(Inst)); |
| 106 | break; |
| 107 | case Inst::Call: |
| 108 | lowerCall(llvm::dyn_cast<InstCall>(Inst)); |
| 109 | break; |
| 110 | case Inst::Cast: |
| 111 | lowerCast(llvm::dyn_cast<InstCast>(Inst)); |
| 112 | break; |
| 113 | case Inst::Fcmp: |
| 114 | lowerFcmp(llvm::dyn_cast<InstFcmp>(Inst)); |
| 115 | break; |
| 116 | case Inst::Icmp: |
| 117 | lowerIcmp(llvm::dyn_cast<InstIcmp>(Inst)); |
| 118 | break; |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 119 | case Inst::IntrinsicCall: |
| 120 | lowerIntrinsicCall(llvm::dyn_cast<InstIntrinsicCall>(Inst)); |
| 121 | break; |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 122 | case Inst::Load: |
| 123 | lowerLoad(llvm::dyn_cast<InstLoad>(Inst)); |
| 124 | break; |
| 125 | case Inst::Phi: |
| 126 | lowerPhi(llvm::dyn_cast<InstPhi>(Inst)); |
| 127 | break; |
| 128 | case Inst::Ret: |
| 129 | lowerRet(llvm::dyn_cast<InstRet>(Inst)); |
| 130 | break; |
| 131 | case Inst::Select: |
| 132 | lowerSelect(llvm::dyn_cast<InstSelect>(Inst)); |
| 133 | break; |
| 134 | case Inst::Store: |
| 135 | lowerStore(llvm::dyn_cast<InstStore>(Inst)); |
| 136 | break; |
| 137 | case Inst::Switch: |
| 138 | lowerSwitch(llvm::dyn_cast<InstSwitch>(Inst)); |
| 139 | break; |
| 140 | case Inst::Unreachable: |
| 141 | lowerUnreachable(llvm::dyn_cast<InstUnreachable>(Inst)); |
| 142 | break; |
| 143 | case Inst::FakeDef: |
| 144 | case Inst::FakeUse: |
| 145 | case Inst::FakeKill: |
| 146 | case Inst::Target: |
| 147 | // These are all Target instruction types and shouldn't be |
| 148 | // encountered at this stage. |
| 149 | Func->setError("Can't lower unsupported instruction type"); |
| 150 | break; |
| 151 | } |
| 152 | Inst->setDeleted(); |
| 153 | |
| 154 | postLower(); |
| 155 | |
| 156 | Context.advanceCur(); |
| 157 | Context.advanceNext(); |
| 158 | } |
| 159 | |
Jim Stichnoth | d97c7df | 2014-06-04 11:57:08 -0700 | [diff] [blame] | 160 | // Drives register allocation, allowing all physical registers (except |
| 161 | // perhaps for the frame pointer) to be allocated. This set of |
| 162 | // registers could potentially be parameterized if we want to restrict |
| 163 | // registers e.g. for performance testing. |
| 164 | void TargetLowering::regAlloc() { |
| 165 | LinearScan LinearScan(Func); |
| 166 | RegSetMask RegInclude = RegSet_None; |
| 167 | RegSetMask RegExclude = RegSet_None; |
| 168 | RegInclude |= RegSet_CallerSave; |
| 169 | RegInclude |= RegSet_CalleeSave; |
Jim Stichnoth | d97c7df | 2014-06-04 11:57:08 -0700 | [diff] [blame] | 170 | if (hasFramePointer()) |
| 171 | RegExclude |= RegSet_FramePointer; |
| 172 | llvm::SmallBitVector RegMask = getRegisterSet(RegInclude, RegExclude); |
| 173 | LinearScan.scan(RegMask); |
| 174 | } |
| 175 | |
Jim Stichnoth | de4ca71 | 2014-06-29 08:13:48 -0700 | [diff] [blame] | 176 | TargetGlobalInitLowering * |
| 177 | TargetGlobalInitLowering::createLowering(TargetArch Target, |
| 178 | GlobalContext *Ctx) { |
| 179 | // These statements can be #ifdef'd to specialize the code generator |
| 180 | // to a subset of the available targets. TODO: use CRTP. |
| 181 | if (Target == Target_X8632) |
| 182 | return TargetGlobalInitX8632::create(Ctx); |
| 183 | #if 0 |
| 184 | if (Target == Target_X8664) |
| 185 | return IceTargetGlobalInitX8664::create(Ctx); |
| 186 | if (Target == Target_ARM32) |
| 187 | return IceTargetGlobalInitARM32::create(Ctx); |
| 188 | if (Target == Target_ARM64) |
| 189 | return IceTargetGlobalInitARM64::create(Ctx); |
| 190 | #endif |
| 191 | llvm_unreachable("Unsupported target"); |
| 192 | return NULL; |
| 193 | } |
| 194 | |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 195 | } // end of namespace Ice |