OLD | NEW |
1 //===- subzero/src/IceCfgNode.cpp - Basic block (node) implementation -----===// | 1 //===- subzero/src/IceCfgNode.cpp - Basic block (node) implementation -----===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file implements the CfgNode class, including the complexities | 10 // This file implements the CfgNode class, including the complexities |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 // assumes this ordering of instructions. | 108 // assumes this ordering of instructions. |
109 // | 109 // |
110 // Note that this transformation takes the Phi dest variables out of | 110 // Note that this transformation takes the Phi dest variables out of |
111 // SSA form, as there may be assignments to the dest variable in | 111 // SSA form, as there may be assignments to the dest variable in |
112 // multiple blocks. | 112 // multiple blocks. |
113 // | 113 // |
114 // TODO: Defer this pass until after register allocation, then split | 114 // TODO: Defer this pass until after register allocation, then split |
115 // critical edges, add the assignments, and lower them. This should | 115 // critical edges, add the assignments, and lower them. This should |
116 // reduce the amount of shuffling at the end of each block. | 116 // reduce the amount of shuffling at the end of each block. |
117 void CfgNode::placePhiStores() { | 117 void CfgNode::placePhiStores() { |
118 // Find the insertion point. TODO: After branch/compare fusing is | 118 // Find the insertion point. |
119 // implemented, try not to insert Phi stores between the compare and | |
120 // conditional branch instructions, otherwise the branch/compare | |
121 // pattern matching may fail. However, the branch/compare sequence | |
122 // will have to be broken if the compare result is read (by the | |
123 // assignment) before it is written (by the compare). | |
124 InstList::iterator InsertionPoint = Insts.end(); | 119 InstList::iterator InsertionPoint = Insts.end(); |
125 // Every block must end in a terminator instruction. | 120 // Every block must end in a terminator instruction, and therefore |
| 121 // must have at least one instruction, so it's valid to decrement |
| 122 // InsertionPoint (but assert just in case). |
126 assert(InsertionPoint != Insts.begin()); | 123 assert(InsertionPoint != Insts.begin()); |
127 --InsertionPoint; | 124 --InsertionPoint; |
128 // Confirm that InsertionPoint is a terminator instruction. Calling | 125 // Confirm that InsertionPoint is a terminator instruction. Calling |
129 // getTerminatorEdges() on a non-terminator instruction will cause | 126 // getTerminatorEdges() on a non-terminator instruction will cause |
130 // an llvm_unreachable(). | 127 // an llvm_unreachable(). |
131 (void)(*InsertionPoint)->getTerminatorEdges(); | 128 (void)(*InsertionPoint)->getTerminatorEdges(); |
| 129 // SafeInsertionPoint is always immediately before the terminator |
| 130 // instruction. If the block ends in a compare and conditional |
| 131 // branch, it's better to place the Phi store before the compare so |
| 132 // as not to interfere with compare/branch fusing. However, if the |
| 133 // compare instruction's dest operand is the same as the new |
| 134 // assignment statement's source operand, this can't be done due to |
| 135 // data dependences, so we need to fall back to the |
| 136 // SafeInsertionPoint. To illustrate: |
| 137 // ; <label>:95 |
| 138 // %97 = load i8* %96, align 1 |
| 139 // %98 = icmp ne i8 %97, 0 |
| 140 // br i1 %98, label %99, label %2132 |
| 141 // ; <label>:99 |
| 142 // %100 = phi i8 [ %97, %95 ], [ %110, %108 ] |
| 143 // %101 = phi i1 [ %98, %95 ], [ %111, %108 ] |
| 144 // would be Phi-lowered as: |
| 145 // ; <label>:95 |
| 146 // %97 = load i8* %96, align 1 |
| 147 // %100_phi = %97 ; can be at InsertionPoint |
| 148 // %98 = icmp ne i8 %97, 0 |
| 149 // %101_phi = %98 ; must be at SafeInsertionPoint |
| 150 // br i1 %98, label %99, label %2132 |
| 151 // ; <label>:99 |
| 152 // %100 = %100_phi |
| 153 // %101 = %101_phi |
| 154 // |
| 155 // TODO(stichnot): It may be possible to bypass this whole |
| 156 // SafeInsertionPoint mechanism. If a source basic block ends in a |
| 157 // conditional branch: |
| 158 // labelSource: |
| 159 // ... |
| 160 // br i1 %foo, label %labelTrue, label %labelFalse |
| 161 // and a branch target has a Phi involving the branch operand: |
| 162 // labelTrue: |
| 163 // %bar = phi i1 [ %foo, %labelSource ], ... |
| 164 // then we actually know the constant i1 value of the Phi operand: |
| 165 // labelTrue: |
| 166 // %bar = phi i1 [ true, %labelSource ], ... |
| 167 // It seems that this optimization should be done by clang or opt, |
| 168 // but we could also do it here. |
| 169 InstList::iterator SafeInsertionPoint = InsertionPoint; |
| 170 // Keep track of the dest variable of a compare instruction, so that |
| 171 // we insert the new instruction at the SafeInsertionPoint if the |
| 172 // compare's dest matches the Phi-lowered assignment's source. |
| 173 Variable *CmpInstDest = NULL; |
132 // If the current insertion point is at a conditional branch | 174 // If the current insertion point is at a conditional branch |
133 // instruction, and the previous instruction is a compare | 175 // instruction, and the previous instruction is a compare |
134 // instruction, then we move the insertion point before the compare | 176 // instruction, then we move the insertion point before the compare |
135 // instruction so as not to interfere with compare/branch fusing. | 177 // instruction so as not to interfere with compare/branch fusing. |
136 if (InstBr *Branch = llvm::dyn_cast<InstBr>(*InsertionPoint)) { | 178 if (InstBr *Branch = llvm::dyn_cast<InstBr>(*InsertionPoint)) { |
137 if (!Branch->isUnconditional()) { | 179 if (!Branch->isUnconditional()) { |
138 if (InsertionPoint != Insts.begin()) { | 180 if (InsertionPoint != Insts.begin()) { |
139 --InsertionPoint; | 181 --InsertionPoint; |
140 if (!llvm::isa<InstIcmp>(*InsertionPoint) && | 182 if (llvm::isa<InstIcmp>(*InsertionPoint) || |
141 !llvm::isa<InstFcmp>(*InsertionPoint)) { | 183 llvm::isa<InstFcmp>(*InsertionPoint)) { |
| 184 CmpInstDest = (*InsertionPoint)->getDest(); |
| 185 } else { |
142 ++InsertionPoint; | 186 ++InsertionPoint; |
143 } | 187 } |
144 } | 188 } |
145 } | 189 } |
146 } | 190 } |
147 | 191 |
148 // Consider every out-edge. | 192 // Consider every out-edge. |
149 for (NodeList::const_iterator I1 = OutEdges.begin(), E1 = OutEdges.end(); | 193 for (NodeList::const_iterator I1 = OutEdges.begin(), E1 = OutEdges.end(); |
150 I1 != E1; ++I1) { | 194 I1 != E1; ++I1) { |
151 CfgNode *Target = *I1; | 195 CfgNode *Target = *I1; |
152 // Consider every Phi instruction at the out-edge. | 196 // Consider every Phi instruction at the out-edge. |
153 for (PhiList::const_iterator I2 = Target->Phis.begin(), | 197 for (PhiList::const_iterator I2 = Target->Phis.begin(), |
154 E2 = Target->Phis.end(); | 198 E2 = Target->Phis.end(); |
155 I2 != E2; ++I2) { | 199 I2 != E2; ++I2) { |
156 Operand *Operand = (*I2)->getOperandForTarget(this); | 200 Operand *Operand = (*I2)->getOperandForTarget(this); |
157 assert(Operand); | 201 assert(Operand); |
158 Variable *Dest = (*I2)->getDest(); | 202 Variable *Dest = (*I2)->getDest(); |
159 assert(Dest); | 203 assert(Dest); |
160 InstAssign *NewInst = InstAssign::create(Func, Dest, Operand); | 204 InstAssign *NewInst = InstAssign::create(Func, Dest, Operand); |
161 // If Src is a variable, set the Src and Dest variables to | 205 // If Src is a variable, set the Src and Dest variables to |
162 // prefer each other for register allocation. | 206 // prefer each other for register allocation. |
163 if (Variable *Src = llvm::dyn_cast<Variable>(Operand)) { | 207 if (Variable *Src = llvm::dyn_cast<Variable>(Operand)) { |
164 bool AllowOverlap = false; | 208 bool AllowOverlap = false; |
165 Dest->setPreferredRegister(Src, AllowOverlap); | 209 Dest->setPreferredRegister(Src, AllowOverlap); |
166 Src->setPreferredRegister(Dest, AllowOverlap); | 210 Src->setPreferredRegister(Dest, AllowOverlap); |
167 } | 211 } |
168 Insts.insert(InsertionPoint, NewInst); | 212 if (CmpInstDest == Operand) |
| 213 Insts.insert(SafeInsertionPoint, NewInst); |
| 214 else |
| 215 Insts.insert(InsertionPoint, NewInst); |
169 NewInst->updateVars(this); | 216 NewInst->updateVars(this); |
170 } | 217 } |
171 } | 218 } |
172 } | 219 } |
173 | 220 |
174 // Deletes the phi instructions after the loads and stores are placed. | 221 // Deletes the phi instructions after the loads and stores are placed. |
175 void CfgNode::deletePhis() { | 222 void CfgNode::deletePhis() { |
176 for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { | 223 for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { |
177 (*I)->setDeleted(); | 224 (*I)->setDeleted(); |
178 } | 225 } |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 I != E; ++I) { | 550 I != E; ++I) { |
504 if (I != OutEdges.begin()) | 551 if (I != OutEdges.begin()) |
505 Str << ", "; | 552 Str << ", "; |
506 Str << "%" << (*I)->getName(); | 553 Str << "%" << (*I)->getName(); |
507 } | 554 } |
508 Str << "\n"; | 555 Str << "\n"; |
509 } | 556 } |
510 } | 557 } |
511 | 558 |
512 } // end of namespace Ice | 559 } // end of namespace Ice |
OLD | NEW |