1818#include " llvm/Analysis/CmpInstAnalysis.h"
1919#include " llvm/Analysis/ConstantFolding.h"
2020#include " llvm/Analysis/InstructionSimplify.h"
21+ #include " llvm/Analysis/Utils/Local.h"
2122#include " llvm/Analysis/VectorUtils.h"
2223#include " llvm/IR/ConstantRange.h"
2324#include " llvm/IR/DataLayout.h"
@@ -413,7 +414,7 @@ Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
413414// / Returns true if we can rewrite Start as a GEP with pointer Base
414415// / and some integer offset. The nodes that need to be re-written
415416// / for this transformation will be added to Explored.
416- static bool canRewriteGEPAsOffset (Type *ElemTy, Value *Start, Value *Base,
417+ static bool canRewriteGEPAsOffset (Value *Start, Value *Base,
417418 const DataLayout &DL,
418419 SetVector<Value *> &Explored) {
419420 SmallVector<Value *, 16 > WorkList (1 , Start);
@@ -447,11 +448,9 @@ static bool canRewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
447448 return false ;
448449
449450 if (auto *GEP = dyn_cast<GEPOperator>(V)) {
450- // We're limiting the GEP to having one index. This will preserve
451- // the original pointer type. We could handle more cases in the
452- // future.
453- if (GEP->getNumIndices () != 1 || !GEP->isInBounds () ||
454- GEP->getSourceElementType () != ElemTy)
451+ // Only allow inbounds GEPs with at most one variable offset.
452+ auto IsNonConst = [](Value *V) { return !isa<ConstantInt>(V); };
453+ if (!GEP->isInBounds () || count_if (GEP->indices (), IsNonConst) > 1 )
455454 return false ;
456455
457456 if (!Explored.contains (GEP->getOperand (0 )))
@@ -528,7 +527,7 @@ static void setInsertionPoint(IRBuilder<> &Builder, Value *V,
528527
529528// / Returns a re-written value of Start as an indexed GEP using Base as a
530529// / pointer.
531- static Value *rewriteGEPAsOffset (Type *ElemTy, Value *Start, Value *Base,
530+ static Value *rewriteGEPAsOffset (Value *Start, Value *Base,
532531 const DataLayout &DL,
533532 SetVector<Value *> &Explored,
534533 InstCombiner &IC) {
@@ -559,29 +558,18 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
559558
560559 // Create all the other instructions.
561560 for (Value *Val : Explored) {
562-
563561 if (NewInsts.contains (Val))
564562 continue ;
565563
566564 if (auto *GEP = dyn_cast<GEPOperator>(Val)) {
567- Value *Index = NewInsts[GEP->getOperand (1 )] ? NewInsts[GEP->getOperand (1 )]
568- : GEP->getOperand (1 );
569565 setInsertionPoint (Builder, GEP);
570- // Indices might need to be sign extended. GEPs will magically do
571- // this, but we need to do it ourselves here.
572- if (Index->getType ()->getScalarSizeInBits () !=
573- NewInsts[GEP->getOperand (0 )]->getType ()->getScalarSizeInBits ()) {
574- Index = Builder.CreateSExtOrTrunc (
575- Index, NewInsts[GEP->getOperand (0 )]->getType (),
576- GEP->getOperand (0 )->getName () + " .sext" );
577- }
578-
579- auto *Op = NewInsts[GEP->getOperand (0 )];
566+ Value *Op = NewInsts[GEP->getOperand (0 )];
567+ Value *OffsetV = emitGEPOffset (&Builder, DL, GEP);
580568 if (isa<ConstantInt>(Op) && cast<ConstantInt>(Op)->isZero ())
581- NewInsts[GEP] = Index ;
569+ NewInsts[GEP] = OffsetV ;
582570 else
583571 NewInsts[GEP] = Builder.CreateNSWAdd (
584- Op, Index , GEP->getOperand (0 )->getName () + " .add" );
572+ Op, OffsetV , GEP->getOperand (0 )->getName () + " .add" );
585573 continue ;
586574 }
587575 if (isa<PHINode>(Val))
@@ -609,23 +597,14 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
609597 }
610598 }
611599
612- PointerType *PtrTy = PointerType::get (
613- Base->getContext (), Start->getType ()->getPointerAddressSpace ());
614600 for (Value *Val : Explored) {
615601 if (Val == Base)
616602 continue ;
617603
618- // Depending on the type, for external users we have to emit
619- // a GEP or a GEP + ptrtoint.
620604 setInsertionPoint (Builder, Val, false );
621-
622- // Cast base to the expected type.
623- Value *NewVal = Builder.CreateBitOrPointerCast (
624- Base, PtrTy, Start->getName () + " to.ptr" );
625- NewVal = Builder.CreateInBoundsGEP (ElemTy, NewVal, ArrayRef (NewInsts[Val]),
626- Val->getName () + " .ptr" );
627- NewVal = Builder.CreateBitOrPointerCast (
628- NewVal, Val->getType (), Val->getName () + " .conv" );
605+ // Create GEP for external users.
606+ Value *NewVal = Builder.CreateInBoundsGEP (
607+ Builder.getInt8Ty (), Base, NewInsts[Val], Val->getName () + " .ptr" );
629608 IC.replaceInstUsesWith (*cast<Instruction>(Val), NewVal);
630609 // Add old instruction to worklist for DCE. We don't directly remove it
631610 // here because the original compare is one of the users.
@@ -635,32 +614,6 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
635614 return NewInsts[Start];
636615}
637616
638- // / Looks through GEPs in order to express the input Value as a constant
639- // / indexed GEP. Returns a pair containing the GEPs Pointer and Index.
640- static std::pair<Value *, Value *>
641- getAsConstantIndexedAddress (Type *ElemTy, Value *V, const DataLayout &DL) {
642- Type *IndexType = IntegerType::get (V->getContext (),
643- DL.getIndexTypeSizeInBits (V->getType ()));
644-
645- Constant *Index = ConstantInt::getNullValue (IndexType);
646- while (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
647- // We accept only inbouds GEPs here to exclude the possibility of
648- // overflow.
649- if (!GEP->isInBounds ())
650- break ;
651- if (GEP->hasAllConstantIndices () && GEP->getNumIndices () == 1 &&
652- GEP->getSourceElementType () == ElemTy &&
653- GEP->getOperand (1 )->getType () == IndexType) {
654- V = GEP->getOperand (0 );
655- Constant *GEPIndex = static_cast <Constant *>(GEP->getOperand (1 ));
656- Index = ConstantExpr::getAdd (Index, GEPIndex);
657- continue ;
658- }
659- break ;
660- }
661- return {V, Index};
662- }
663-
664617// / Converts (CMP GEPLHS, RHS) if this change would make RHS a constant.
665618// / We can look through PHIs, GEPs and casts in order to determine a common base
666619// / between GEPLHS and RHS.
@@ -675,14 +628,19 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
675628 if (!GEPLHS->hasAllConstantIndices ())
676629 return nullptr ;
677630
678- Type *ElemTy = GEPLHS->getSourceElementType ();
679- Value *PtrBase, *Index;
680- std::tie (PtrBase, Index) = getAsConstantIndexedAddress (ElemTy, GEPLHS, DL);
631+ APInt Offset (DL.getIndexTypeSizeInBits (GEPLHS->getType ()), 0 );
632+ Value *PtrBase =
633+ GEPLHS->stripAndAccumulateConstantOffsets (DL, Offset,
634+ /* AllowNonInbounds*/ false );
635+
636+ // Bail if we looked through addrspacecast.
637+ if (PtrBase->getType () != GEPLHS->getType ())
638+ return nullptr ;
681639
682640 // The set of nodes that will take part in this transformation.
683641 SetVector<Value *> Nodes;
684642
685- if (!canRewriteGEPAsOffset (ElemTy, RHS, PtrBase, DL, Nodes))
643+ if (!canRewriteGEPAsOffset (RHS, PtrBase, DL, Nodes))
686644 return nullptr ;
687645
688646 // We know we can re-write this as
@@ -691,13 +649,14 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
691649 // can't have overflow on either side. We can therefore re-write
692650 // this as:
693651 // OFFSET1 cmp OFFSET2
694- Value *NewRHS = rewriteGEPAsOffset (ElemTy, RHS, PtrBase, DL, Nodes, IC);
652+ Value *NewRHS = rewriteGEPAsOffset (RHS, PtrBase, DL, Nodes, IC);
695653
696654 // RewriteGEPAsOffset has replaced RHS and all of its uses with a re-written
697655 // GEP having PtrBase as the pointer base, and has returned in NewRHS the
698656 // offset. Since Index is the offset of LHS to the base pointer, we will now
699657 // compare the offsets instead of comparing the pointers.
700- return new ICmpInst (ICmpInst::getSignedPredicate (Cond), Index, NewRHS);
658+ return new ICmpInst (ICmpInst::getSignedPredicate (Cond),
659+ IC.Builder .getInt (Offset), NewRHS);
701660}
702661
703662// / Fold comparisons between a GEP instruction and something else. At this point
0 commit comments