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. |
126 assert(InsertionPoint != Insts.begin()); | 121 assert(InsertionPoint != Insts.begin()); |
127 --InsertionPoint; | 122 --InsertionPoint; |
123 // SafeInsertionPoint is always immediately before the terminator | |
124 // instruction. If the block ends in a compare and conditional | |
125 // branch, it's better to place the Phi store before the compare so | |
126 // as not to interfere with compare/branch fusing. However, if the | |
127 // compare instruction's dest operand is the same as the new | |
128 // assignment statement's source operand, this can't be done due to | |
129 // data dependences, so we need to fall back to the | |
130 // SafeInsertionPoint. To illustrate: | |
131 // ; <label>:95 | |
132 // %97 = load i8* %96, align 1 | |
133 // %98 = icmp ne i8 %97, 0 | |
134 // br i1 %98, label %99, label %2132 | |
135 // ; <label>:99 | |
136 // %100 = phi i8 [ %97, %95 ], [ %110, %108 ] | |
137 // %101 = phi i1 [ %98, %95 ], [ %111, %108 ] | |
138 // would be Phi-lowered as: | |
139 // ; <label>:95 | |
140 // %97 = load i8* %96, align 1 | |
141 // %100_phi = %97 ; can be at InsertionPoint | |
142 // %98 = icmp ne i8 %97, 0 | |
143 // %101_phi = %98 ; must be at SafeInsertionPoint | |
144 // br i1 %98, label %99, label %2132 | |
145 // ; <label>:99 | |
146 // %100 = %100_phi | |
147 // %101 = %101_phi | |
148 InstList::iterator SafeInsertionPoint = InsertionPoint; | |
149 // Keep track of the dest variable of a compare instruction, so that | |
150 // we insert the new instruction at the SafeInsertionPoint if the | |
151 // compare's dest matches the Phi-lowered assignment's source. | |
152 Variable *CmpInstDest = NULL; | |
128 // Confirm that InsertionPoint is a terminator instruction. Calling | 153 // Confirm that InsertionPoint is a terminator instruction. Calling |
129 // getTerminatorEdges() on a non-terminator instruction will cause | 154 // getTerminatorEdges() on a non-terminator instruction will cause |
130 // an llvm_unreachable(). | 155 // an llvm_unreachable(). |
jvoung (off chromium)
2014/09/10 17:17:43
Maybe this confirmation should be earlier than the
Jim Stichnoth
2014/09/10 18:29:16
Actually, the "Every block must..." comment was me
| |
131 (void)(*InsertionPoint)->getTerminatorEdges(); | 156 (void)(*InsertionPoint)->getTerminatorEdges(); |
132 // If the current insertion point is at a conditional branch | 157 // If the current insertion point is at a conditional branch |
133 // instruction, and the previous instruction is a compare | 158 // instruction, and the previous instruction is a compare |
134 // instruction, then we move the insertion point before the compare | 159 // instruction, then we move the insertion point before the compare |
135 // instruction so as not to interfere with compare/branch fusing. | 160 // instruction so as not to interfere with compare/branch fusing. |
136 if (InstBr *Branch = llvm::dyn_cast<InstBr>(*InsertionPoint)) { | 161 if (InstBr *Branch = llvm::dyn_cast<InstBr>(*InsertionPoint)) { |
137 if (!Branch->isUnconditional()) { | 162 if (!Branch->isUnconditional()) { |
138 if (InsertionPoint != Insts.begin()) { | 163 if (InsertionPoint != Insts.begin()) { |
139 --InsertionPoint; | 164 --InsertionPoint; |
140 if (!llvm::isa<InstIcmp>(*InsertionPoint) && | 165 if (llvm::isa<InstIcmp>(*InsertionPoint) || |
141 !llvm::isa<InstFcmp>(*InsertionPoint)) { | 166 llvm::isa<InstFcmp>(*InsertionPoint)) { |
167 CmpInstDest = (*InsertionPoint)->getDest(); | |
168 } else { | |
142 ++InsertionPoint; | 169 ++InsertionPoint; |
143 } | 170 } |
144 } | 171 } |
145 } | 172 } |
146 } | 173 } |
147 | 174 |
148 // Consider every out-edge. | 175 // Consider every out-edge. |
149 for (NodeList::const_iterator I1 = OutEdges.begin(), E1 = OutEdges.end(); | 176 for (NodeList::const_iterator I1 = OutEdges.begin(), E1 = OutEdges.end(); |
150 I1 != E1; ++I1) { | 177 I1 != E1; ++I1) { |
151 CfgNode *Target = *I1; | 178 CfgNode *Target = *I1; |
152 // Consider every Phi instruction at the out-edge. | 179 // Consider every Phi instruction at the out-edge. |
153 for (PhiList::const_iterator I2 = Target->Phis.begin(), | 180 for (PhiList::const_iterator I2 = Target->Phis.begin(), |
154 E2 = Target->Phis.end(); | 181 E2 = Target->Phis.end(); |
155 I2 != E2; ++I2) { | 182 I2 != E2; ++I2) { |
156 Operand *Operand = (*I2)->getOperandForTarget(this); | 183 Operand *Operand = (*I2)->getOperandForTarget(this); |
157 assert(Operand); | 184 assert(Operand); |
158 Variable *Dest = (*I2)->getDest(); | 185 Variable *Dest = (*I2)->getDest(); |
159 assert(Dest); | 186 assert(Dest); |
160 InstAssign *NewInst = InstAssign::create(Func, Dest, Operand); | 187 InstAssign *NewInst = InstAssign::create(Func, Dest, Operand); |
161 // If Src is a variable, set the Src and Dest variables to | 188 // If Src is a variable, set the Src and Dest variables to |
162 // prefer each other for register allocation. | 189 // prefer each other for register allocation. |
163 if (Variable *Src = llvm::dyn_cast<Variable>(Operand)) { | 190 if (Variable *Src = llvm::dyn_cast<Variable>(Operand)) { |
164 bool AllowOverlap = false; | 191 bool AllowOverlap = false; |
165 Dest->setPreferredRegister(Src, AllowOverlap); | 192 Dest->setPreferredRegister(Src, AllowOverlap); |
166 Src->setPreferredRegister(Dest, AllowOverlap); | 193 Src->setPreferredRegister(Dest, AllowOverlap); |
167 } | 194 } |
168 Insts.insert(InsertionPoint, NewInst); | 195 if (CmpInstDest == Operand) |
196 Insts.insert(SafeInsertionPoint, NewInst); | |
197 else | |
198 Insts.insert(InsertionPoint, NewInst); | |
169 NewInst->updateVars(this); | 199 NewInst->updateVars(this); |
170 } | 200 } |
171 } | 201 } |
172 } | 202 } |
173 | 203 |
174 // Deletes the phi instructions after the loads and stores are placed. | 204 // Deletes the phi instructions after the loads and stores are placed. |
175 void CfgNode::deletePhis() { | 205 void CfgNode::deletePhis() { |
176 for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { | 206 for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { |
177 (*I)->setDeleted(); | 207 (*I)->setDeleted(); |
178 } | 208 } |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
503 I != E; ++I) { | 533 I != E; ++I) { |
504 if (I != OutEdges.begin()) | 534 if (I != OutEdges.begin()) |
505 Str << ", "; | 535 Str << ", "; |
506 Str << "%" << (*I)->getName(); | 536 Str << "%" << (*I)->getName(); |
507 } | 537 } |
508 Str << "\n"; | 538 Str << "\n"; |
509 } | 539 } |
510 } | 540 } |
511 | 541 |
512 } // end of namespace Ice | 542 } // end of namespace Ice |
OLD | NEW |