@@ -176,40 +176,37 @@ BCEAtom visitICmpLoadOperand(Value *const Val, BaseIdentifier &BaseId) {
176176 Offset);
177177}
178178
179- // A basic block with a comparison between two BCE atoms, e.g. `a == o.a` in the
180- // example at the top.
181- // The block might do extra work besides the atom comparison, in which case
182- // doesOtherWork() returns true. Under some conditions, the block can be
183- // split into the atom comparison part and the "other work" part
184- // (see canSplit()).
179+ // A comparison between two BCE atoms, e.g. `a == o.a` in the example at the
180+ // top.
185181// Note: the terminology is misleading: the comparison is symmetric, so there
186182// is no real {l/r}hs. What we want though is to have the same base on the
187183// left (resp. right), so that we can detect consecutive loads. To ensure this
188184// we put the smallest atom on the left.
189- class BCECmpBlock {
190- public:
191- BCECmpBlock () {}
185+ struct BCECmp {
186+ BCEAtom Lhs;
187+ BCEAtom Rhs;
188+ int SizeBits;
189+ const ICmpInst *CmpI;
192190
193- BCECmpBlock (BCEAtom L, BCEAtom R, int SizeBits)
194- : Lhs_ (std::move(L)), Rhs_ (std::move(R)), SizeBits_ (SizeBits) {
195- if (Rhs_ < Lhs_ ) std::swap (Rhs_, Lhs_ );
191+ BCECmp (BCEAtom L, BCEAtom R, int SizeBits, const ICmpInst *CmpI )
192+ : Lhs (std::move(L)), Rhs (std::move(R)), SizeBits (SizeBits), CmpI(CmpI ) {
193+ if (Rhs < Lhs ) std::swap (Rhs, Lhs );
196194 }
195+ };
197196
198- bool IsValid () const { return Lhs_.BaseId != 0 && Rhs_.BaseId != 0 ; }
199-
200- // Assert the block is consistent: If valid, it should also have
201- // non-null members besides Lhs_ and Rhs_.
202- void AssertConsistent () const {
203- if (IsValid ()) {
204- assert (BB);
205- assert (CmpI);
206- assert (BranchI);
207- }
208- }
197+ // A basic block with a comparison between two BCE atoms.
198+ // The block might do extra work besides the atom comparison, in which case
199+ // doesOtherWork() returns true. Under some conditions, the block can be
200+ // split into the atom comparison part and the "other work" part
201+ // (see canSplit()).
202+ class BCECmpBlock {
203+ public:
204+ BCECmpBlock (BCECmp Cmp, BasicBlock *BB, BranchInst *BranchI)
205+ : BB(BB), BranchI(BranchI), Cmp(std::move(Cmp)) {}
209206
210- const BCEAtom &Lhs () const { return Lhs_ ; }
211- const BCEAtom &Rhs () const { return Rhs_ ; }
212- int SizeBits () const { return SizeBits_ ; }
207+ const BCEAtom &Lhs () const { return Cmp. Lhs ; }
208+ const BCEAtom &Rhs () const { return Cmp. Rhs ; }
209+ int SizeBits () const { return Cmp. SizeBits ; }
213210
214211 // Returns true if the block does other works besides comparison.
215212 bool doesOtherWork () const ;
@@ -222,7 +219,7 @@ class BCECmpBlock {
222219 // be sunk below this instruction. By doing this, we know we can separate the
223220 // BCE-cmp-block instructions from the non-BCE-cmp-block instructions in the
224221 // block.
225- bool canSinkBCECmpInst (const Instruction *, DenseSet<Instruction *> &,
222+ bool canSinkBCECmpInst (const Instruction *, DenseSet<const Instruction *> &,
226223 AliasAnalysis &AA) const ;
227224
228225 // We can separate the BCE-cmp-block instructions and the non-BCE-cmp-block
@@ -231,22 +228,18 @@ class BCECmpBlock {
231228 void split (BasicBlock *NewParent, AliasAnalysis &AA) const ;
232229
233230 // The basic block where this comparison happens.
234- BasicBlock *BB = nullptr ;
235- // The ICMP for this comparison.
236- ICmpInst *CmpI = nullptr ;
231+ BasicBlock *BB;
237232 // The terminating branch.
238- BranchInst *BranchI = nullptr ;
233+ BranchInst *BranchI;
239234 // The block requires splitting.
240235 bool RequireSplit = false ;
241236
242237private:
243- BCEAtom Lhs_;
244- BCEAtom Rhs_;
245- int SizeBits_ = 0 ;
238+ BCECmp Cmp;
246239};
247240
248241bool BCECmpBlock::canSinkBCECmpInst (const Instruction *Inst,
249- DenseSet<Instruction *> &BlockInsts,
242+ DenseSet<const Instruction *> &BlockInsts,
250243 AliasAnalysis &AA) const {
251244 // If this instruction may clobber the loads and is in middle of the BCE cmp
252245 // block instructions, then bail for now.
@@ -255,8 +248,8 @@ bool BCECmpBlock::canSinkBCECmpInst(const Instruction *Inst,
255248 if (!isSimpleLoadOrStore (Inst))
256249 return false ;
257250 // Disallow stores that might alias the BCE operands
258- MemoryLocation LLoc = MemoryLocation::get (Lhs_ .LoadI );
259- MemoryLocation RLoc = MemoryLocation::get (Rhs_ .LoadI );
251+ MemoryLocation LLoc = MemoryLocation::get (Cmp. Lhs .LoadI );
252+ MemoryLocation RLoc = MemoryLocation::get (Cmp. Rhs .LoadI );
260253 if (isModSet (AA.getModRefInfo (Inst, LLoc)) ||
261254 isModSet (AA.getModRefInfo (Inst, RLoc)))
262255 return false ;
@@ -271,8 +264,9 @@ bool BCECmpBlock::canSinkBCECmpInst(const Instruction *Inst,
271264}
272265
273266void BCECmpBlock::split (BasicBlock *NewParent, AliasAnalysis &AA) const {
274- DenseSet<Instruction *> BlockInsts (
275- {Lhs_.GEP , Rhs_.GEP , Lhs_.LoadI , Rhs_.LoadI , CmpI, BranchI});
267+ DenseSet<const Instruction *> BlockInsts (
268+ {Cmp.Lhs .GEP , Cmp.Rhs .GEP , Cmp.Lhs .LoadI , Cmp.Rhs .LoadI , Cmp.CmpI ,
269+ BranchI});
276270 llvm::SmallVector<Instruction *, 4 > OtherInsts;
277271 for (Instruction &Inst : *BB) {
278272 if (BlockInsts.count (&Inst))
@@ -291,8 +285,9 @@ void BCECmpBlock::split(BasicBlock *NewParent, AliasAnalysis &AA) const {
291285}
292286
293287bool BCECmpBlock::canSplit (AliasAnalysis &AA) const {
294- DenseSet<Instruction *> BlockInsts (
295- {Lhs_.GEP , Rhs_.GEP , Lhs_.LoadI , Rhs_.LoadI , CmpI, BranchI});
288+ DenseSet<const Instruction *> BlockInsts (
289+ {Cmp.Lhs .GEP , Cmp.Rhs .GEP , Cmp.Lhs .LoadI , Cmp.Rhs .LoadI , Cmp.CmpI ,
290+ BranchI});
296291 for (Instruction &Inst : *BB) {
297292 if (!BlockInsts.count (&Inst)) {
298293 if (!canSinkBCECmpInst (&Inst, BlockInsts, AA))
@@ -303,10 +298,10 @@ bool BCECmpBlock::canSplit(AliasAnalysis &AA) const {
303298}
304299
305300bool BCECmpBlock::doesOtherWork () const {
306- AssertConsistent ();
307301 // All the instructions we care about in the BCE cmp block.
308- DenseSet<Instruction *> BlockInsts (
309- {Lhs_.GEP , Rhs_.GEP , Lhs_.LoadI , Rhs_.LoadI , CmpI, BranchI});
302+ DenseSet<const Instruction *> BlockInsts (
303+ {Cmp.Lhs .GEP , Cmp.Rhs .GEP , Cmp.Lhs .LoadI , Cmp.Rhs .LoadI , Cmp.CmpI ,
304+ BranchI});
310305 // TODO(courbet): Can we allow some other things ? This is very conservative.
311306 // We might be able to get away with anything does not have any side
312307 // effects outside of the basic block.
@@ -320,55 +315,55 @@ bool BCECmpBlock::doesOtherWork() const {
320315
321316// Visit the given comparison. If this is a comparison between two valid
322317// BCE atoms, returns the comparison.
323- BCECmpBlock visitICmp (const ICmpInst *const CmpI,
324- const ICmpInst::Predicate ExpectedPredicate,
325- BaseIdentifier &BaseId) {
318+ Optional<BCECmp> visitICmp (const ICmpInst *const CmpI,
319+ const ICmpInst::Predicate ExpectedPredicate,
320+ BaseIdentifier &BaseId) {
326321 // The comparison can only be used once:
327322 // - For intermediate blocks, as a branch condition.
328323 // - For the final block, as an incoming value for the Phi.
329324 // If there are any other uses of the comparison, we cannot merge it with
330325 // other comparisons as we would create an orphan use of the value.
331326 if (!CmpI->hasOneUse ()) {
332327 LLVM_DEBUG (dbgs () << " cmp has several uses\n " );
333- return {} ;
328+ return None ;
334329 }
335330 if (CmpI->getPredicate () != ExpectedPredicate)
336- return {} ;
331+ return None ;
337332 LLVM_DEBUG (dbgs () << " cmp "
338333 << (ExpectedPredicate == ICmpInst::ICMP_EQ ? " eq" : " ne" )
339334 << " \n " );
340335 auto Lhs = visitICmpLoadOperand (CmpI->getOperand (0 ), BaseId);
341336 if (!Lhs.BaseId )
342- return {} ;
337+ return None ;
343338 auto Rhs = visitICmpLoadOperand (CmpI->getOperand (1 ), BaseId);
344339 if (!Rhs.BaseId )
345- return {} ;
340+ return None ;
346341 const auto &DL = CmpI->getModule ()->getDataLayout ();
347- return BCECmpBlock (std::move (Lhs), std::move (Rhs),
348- DL.getTypeSizeInBits (CmpI->getOperand (0 )->getType ()));
342+ return BCECmp (std::move (Lhs), std::move (Rhs),
343+ DL.getTypeSizeInBits (CmpI->getOperand (0 )->getType ()), CmpI );
349344}
350345
351346// Visit the given comparison block. If this is a comparison between two valid
352347// BCE atoms, returns the comparison.
353- BCECmpBlock visitCmpBlock (Value *const Val, BasicBlock *const Block,
354- const BasicBlock *const PhiBlock,
355- BaseIdentifier &BaseId) {
356- if (Block->empty ()) return {} ;
348+ Optional< BCECmpBlock> visitCmpBlock (Value *const Val, BasicBlock *const Block,
349+ const BasicBlock *const PhiBlock,
350+ BaseIdentifier &BaseId) {
351+ if (Block->empty ()) return None ;
357352 auto *const BranchI = dyn_cast<BranchInst>(Block->getTerminator ());
358- if (!BranchI) return {} ;
353+ if (!BranchI) return None ;
359354 LLVM_DEBUG (dbgs () << " branch\n " );
360355 if (BranchI->isUnconditional ()) {
361356 // In this case, we expect an incoming value which is the result of the
362357 // comparison. This is the last link in the chain of comparisons (note
363358 // that this does not mean that this is the last incoming value, blocks
364359 // can be reordered).
365360 auto *const CmpI = dyn_cast<ICmpInst>(Val);
366- if (!CmpI) return {} ;
361+ if (!CmpI) return None ;
367362 LLVM_DEBUG (dbgs () << " icmp\n " );
368- auto Result = visitICmp (CmpI, ICmpInst::ICMP_EQ, BaseId);
369- Result. CmpI = CmpI;
370- Result. BranchI = BranchI ;
371- return Result;
363+ Optional<BCECmp> Result = visitICmp (CmpI, ICmpInst::ICMP_EQ, BaseId);
364+ if (!Result)
365+ return None ;
366+ return BCECmpBlock ( std::move (* Result), Block, BranchI) ;
372367 } else {
373368 // In this case, we expect a constant incoming value (the comparison is
374369 // chained).
@@ -381,14 +376,13 @@ BCECmpBlock visitCmpBlock(Value *const Val, BasicBlock *const Block,
381376 LLVM_DEBUG (dbgs () << " icmp\n " );
382377 assert (BranchI->getNumSuccessors () == 2 && " expecting a cond branch" );
383378 BasicBlock *const FalseBlock = BranchI->getSuccessor (1 );
384- auto Result = visitICmp (
379+ Optional<BCECmp> Result = visitICmp (
385380 CmpI, FalseBlock == PhiBlock ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE,
386381 BaseId);
387- Result. CmpI = CmpI;
388- Result. BranchI = BranchI ;
389- return Result;
382+ if (!Result)
383+ return None ;
384+ return BCECmpBlock ( std::move (* Result), Block, BranchI) ;
390385 }
391- return {};
392386}
393387
394388static inline void enqueueBlock (std::vector<BCECmpBlock> &Comparisons,
@@ -442,15 +436,14 @@ BCECmpChain::BCECmpChain(const std::vector<BasicBlock *> &Blocks, PHINode &Phi,
442436 BaseIdentifier BaseId;
443437 for (BasicBlock *const Block : Blocks) {
444438 assert (Block && " invalid block" );
445- BCECmpBlock Comparison = visitCmpBlock (Phi.getIncomingValueForBlock (Block),
446- Block, Phi.getParent (), BaseId);
447- Comparison.BB = Block;
448- if (!Comparison.IsValid ()) {
439+ Optional<BCECmpBlock> Comparison = visitCmpBlock (
440+ Phi.getIncomingValueForBlock (Block), Block, Phi.getParent (), BaseId);
441+ if (!Comparison) {
449442 LLVM_DEBUG (dbgs () << " chain with invalid BCECmpBlock, no merge.\n " );
450443 return ;
451444 }
452- if (Comparison. doesOtherWork ()) {
453- LLVM_DEBUG (dbgs () << " block '" << Comparison. BB ->getName ()
445+ if (Comparison-> doesOtherWork ()) {
446+ LLVM_DEBUG (dbgs () << " block '" << Comparison-> BB ->getName ()
454447 << " ' does extra work besides compare\n " );
455448 if (Comparisons.empty ()) {
456449 // This is the initial block in the chain, in case this block does other
@@ -466,15 +459,15 @@ BCECmpChain::BCECmpChain(const std::vector<BasicBlock *> &Blocks, PHINode &Phi,
466459 // and start anew.
467460 //
468461 // NOTE: we only handle blocks a with single predecessor for now.
469- if (Comparison. canSplit (AA)) {
462+ if (Comparison-> canSplit (AA)) {
470463 LLVM_DEBUG (dbgs ()
471- << " Split initial block '" << Comparison. BB ->getName ()
464+ << " Split initial block '" << Comparison-> BB ->getName ()
472465 << " ' that does extra work besides compare\n " );
473- Comparison. RequireSplit = true ;
474- enqueueBlock (Comparisons, std::move (Comparison));
466+ Comparison-> RequireSplit = true ;
467+ enqueueBlock (Comparisons, std::move (* Comparison));
475468 } else {
476469 LLVM_DEBUG (dbgs ()
477- << " ignoring initial block '" << Comparison. BB ->getName ()
470+ << " ignoring initial block '" << Comparison-> BB ->getName ()
478471 << " ' that does extra work besides compare\n " );
479472 }
480473 continue ;
@@ -504,7 +497,7 @@ BCECmpChain::BCECmpChain(const std::vector<BasicBlock *> &Blocks, PHINode &Phi,
504497 // We could still merge bb1 and bb2 though.
505498 return ;
506499 }
507- enqueueBlock (Comparisons, std::move (Comparison));
500+ enqueueBlock (Comparisons, std::move (* Comparison));
508501 }
509502
510503 // It is possible we have no suitable comparison to merge.
0 commit comments