18
18
#include " llvm/Analysis/CmpInstAnalysis.h"
19
19
#include " llvm/Analysis/ConstantFolding.h"
20
20
#include " llvm/Analysis/InstructionSimplify.h"
21
+ #include " llvm/Analysis/Utils/Local.h"
21
22
#include " llvm/Analysis/VectorUtils.h"
22
23
#include " llvm/IR/ConstantRange.h"
23
24
#include " llvm/IR/DataLayout.h"
@@ -413,7 +414,7 @@ Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
413
414
// / Returns true if we can rewrite Start as a GEP with pointer Base
414
415
// / and some integer offset. The nodes that need to be re-written
415
416
// / 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,
417
418
const DataLayout &DL,
418
419
SetVector<Value *> &Explored) {
419
420
SmallVector<Value *, 16 > WorkList (1 , Start);
@@ -447,11 +448,9 @@ static bool canRewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
447
448
return false ;
448
449
449
450
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 )
455
454
return false ;
456
455
457
456
if (!Explored.contains (GEP->getOperand (0 )))
@@ -528,7 +527,7 @@ static void setInsertionPoint(IRBuilder<> &Builder, Value *V,
528
527
529
528
// / Returns a re-written value of Start as an indexed GEP using Base as a
530
529
// / pointer.
531
- static Value *rewriteGEPAsOffset (Type *ElemTy, Value *Start, Value *Base,
530
+ static Value *rewriteGEPAsOffset (Value *Start, Value *Base,
532
531
const DataLayout &DL,
533
532
SetVector<Value *> &Explored,
534
533
InstCombiner &IC) {
@@ -559,29 +558,18 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
559
558
560
559
// Create all the other instructions.
561
560
for (Value *Val : Explored) {
562
-
563
561
if (NewInsts.contains (Val))
564
562
continue ;
565
563
566
564
if (auto *GEP = dyn_cast<GEPOperator>(Val)) {
567
- Value *Index = NewInsts[GEP->getOperand (1 )] ? NewInsts[GEP->getOperand (1 )]
568
- : GEP->getOperand (1 );
569
565
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);
580
568
if (isa<ConstantInt>(Op) && cast<ConstantInt>(Op)->isZero ())
581
- NewInsts[GEP] = Index ;
569
+ NewInsts[GEP] = OffsetV ;
582
570
else
583
571
NewInsts[GEP] = Builder.CreateNSWAdd (
584
- Op, Index , GEP->getOperand (0 )->getName () + " .add" );
572
+ Op, OffsetV , GEP->getOperand (0 )->getName () + " .add" );
585
573
continue ;
586
574
}
587
575
if (isa<PHINode>(Val))
@@ -609,23 +597,14 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
609
597
}
610
598
}
611
599
612
- PointerType *PtrTy = PointerType::get (
613
- Base->getContext (), Start->getType ()->getPointerAddressSpace ());
614
600
for (Value *Val : Explored) {
615
601
if (Val == Base)
616
602
continue ;
617
603
618
- // Depending on the type, for external users we have to emit
619
- // a GEP or a GEP + ptrtoint.
620
604
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" );
629
608
IC.replaceInstUsesWith (*cast<Instruction>(Val), NewVal);
630
609
// Add old instruction to worklist for DCE. We don't directly remove it
631
610
// here because the original compare is one of the users.
@@ -635,32 +614,6 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
635
614
return NewInsts[Start];
636
615
}
637
616
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
-
664
617
// / Converts (CMP GEPLHS, RHS) if this change would make RHS a constant.
665
618
// / We can look through PHIs, GEPs and casts in order to determine a common base
666
619
// / between GEPLHS and RHS.
@@ -675,14 +628,19 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
675
628
if (!GEPLHS->hasAllConstantIndices ())
676
629
return nullptr ;
677
630
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 ;
681
639
682
640
// The set of nodes that will take part in this transformation.
683
641
SetVector<Value *> Nodes;
684
642
685
- if (!canRewriteGEPAsOffset (ElemTy, RHS, PtrBase, DL, Nodes))
643
+ if (!canRewriteGEPAsOffset (RHS, PtrBase, DL, Nodes))
686
644
return nullptr ;
687
645
688
646
// We know we can re-write this as
@@ -691,13 +649,14 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
691
649
// can't have overflow on either side. We can therefore re-write
692
650
// this as:
693
651
// OFFSET1 cmp OFFSET2
694
- Value *NewRHS = rewriteGEPAsOffset (ElemTy, RHS, PtrBase, DL, Nodes, IC);
652
+ Value *NewRHS = rewriteGEPAsOffset (RHS, PtrBase, DL, Nodes, IC);
695
653
696
654
// RewriteGEPAsOffset has replaced RHS and all of its uses with a re-written
697
655
// GEP having PtrBase as the pointer base, and has returned in NewRHS the
698
656
// offset. Since Index is the offset of LHS to the base pointer, we will now
699
657
// 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);
701
660
}
702
661
703
662
// / Fold comparisons between a GEP instruction and something else. At this point
0 commit comments