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,11 +414,12 @@ 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);
420
421
Explored.insert (Base);
422
+ uint64_t IndexSize = DL.getIndexTypeSizeInBits (Start->getType ());
421
423
422
424
// The following traversal gives us an order which can be used
423
425
// when doing the final transformation. Since in the final
@@ -447,11 +449,11 @@ static bool canRewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
447
449
return false ;
448
450
449
451
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 )
452
+ // Only allow GEPs with at most one variable offset.
453
+ APInt Offset (IndexSize, 0 );
454
+ MapVector<Value *, APInt> VarOffsets;
455
+ if (! GEP->collectOffset (DL, IndexSize, VarOffsets, Offset ) ||
456
+ VarOffsets. size () > 1 )
455
457
return false ;
456
458
457
459
if (!Explored.contains (GEP->getOperand (0 )))
@@ -528,7 +530,7 @@ static void setInsertionPoint(IRBuilder<> &Builder, Value *V,
528
530
529
531
// / Returns a re-written value of Start as an indexed GEP using Base as a
530
532
// / pointer.
531
- static Value *rewriteGEPAsOffset (Type *ElemTy, Value *Start, Value *Base,
533
+ static Value *rewriteGEPAsOffset (Value *Start, Value *Base,
532
534
const DataLayout &DL,
533
535
SetVector<Value *> &Explored,
534
536
InstCombiner &IC) {
@@ -539,8 +541,8 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
539
541
// 3. Add the edges for the PHI nodes.
540
542
// 4. Emit GEPs to get the original pointers.
541
543
// 5. Remove the original instructions.
542
- Type *IndexType = IntegerType::get (
543
- Base->getContext (), DL. getIndexTypeSizeInBits (Start-> getType ()) );
544
+ uint64_t IndexSize = DL. getIndexTypeSizeInBits (Start-> getType ());
545
+ Type *IndexType = IntegerType::get ( Base->getContext (), IndexSize );
544
546
545
547
DenseMap<Value *, Value *> NewInsts;
546
548
NewInsts[Base] = ConstantInt::getNullValue (IndexType);
@@ -559,29 +561,22 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
559
561
560
562
// Create all the other instructions.
561
563
for (Value *Val : Explored) {
562
-
563
564
if (NewInsts.contains (Val))
564
565
continue ;
565
566
566
567
if (auto *GEP = dyn_cast<GEPOperator>(Val)) {
567
- Value *Index = NewInsts[GEP->getOperand (1 )] ? NewInsts[GEP->getOperand (1 )]
568
- : GEP->getOperand (1 );
569
- 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
- }
568
+ APInt Offset (IndexSize, 0 );
569
+ MapVector<Value *, APInt> VarOffsets;
570
+ GEP->collectOffset (DL, IndexSize, VarOffsets, Offset);
578
571
579
- auto *Op = NewInsts[GEP->getOperand (0 )];
572
+ setInsertionPoint (Builder, GEP);
573
+ Value *Op = NewInsts[GEP->getOperand (0 )];
574
+ Value *OffsetV = emitGEPOffset (&Builder, DL, GEP);
580
575
if (isa<ConstantInt>(Op) && cast<ConstantInt>(Op)->isZero ())
581
- NewInsts[GEP] = Index ;
576
+ NewInsts[GEP] = OffsetV ;
582
577
else
583
578
NewInsts[GEP] = Builder.CreateNSWAdd (
584
- Op, Index , GEP->getOperand (0 )->getName () + " .add" );
579
+ Op, OffsetV , GEP->getOperand (0 )->getName () + " .add" );
585
580
continue ;
586
581
}
587
582
if (isa<PHINode>(Val))
@@ -609,23 +604,14 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
609
604
}
610
605
}
611
606
612
- PointerType *PtrTy = PointerType::get (
613
- Base->getContext (), Start->getType ()->getPointerAddressSpace ());
614
607
for (Value *Val : Explored) {
615
608
if (Val == Base)
616
609
continue ;
617
610
618
- // Depending on the type, for external users we have to emit
619
- // a GEP or a GEP + ptrtoint.
620
611
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" );
612
+ // Create GEP for external users.
613
+ Value *NewVal = Builder.CreateInBoundsGEP (
614
+ Builder.getInt8Ty (), Base, NewInsts[Val], Val->getName () + " .ptr" );
629
615
IC.replaceInstUsesWith (*cast<Instruction>(Val), NewVal);
630
616
// Add old instruction to worklist for DCE. We don't directly remove it
631
617
// here because the original compare is one of the users.
@@ -637,28 +623,18 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
637
623
638
624
// / Looks through GEPs in order to express the input Value as a constant
639
625
// / 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);
626
+ static std::pair<Value *, APInt>
627
+ getAsConstantIndexedAddress (Value *V, const DataLayout &DL) {
628
+ APInt Offset = APInt (DL.getIndexTypeSizeInBits (V->getType ()), 0 );
646
629
while (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
647
630
// We accept only inbouds GEPs here to exclude the possibility of
648
631
// overflow.
649
- if (!GEP->isInBounds ())
632
+ if (!GEP->isInBounds () || !GEP-> accumulateConstantOffset (DL, Offset) )
650
633
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 ;
634
+
635
+ V = GEP->getPointerOperand ();
660
636
}
661
- return {V, Index };
637
+ return {V, Offset };
662
638
}
663
639
664
640
// / Converts (CMP GEPLHS, RHS) if this change would make RHS a constant.
@@ -675,14 +651,14 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
675
651
if (!GEPLHS->hasAllConstantIndices ())
676
652
return nullptr ;
677
653
678
- Type *ElemTy = GEPLHS-> getSourceElementType () ;
679
- Value *PtrBase, *Index ;
680
- std::tie (PtrBase, Index ) = getAsConstantIndexedAddress (ElemTy, GEPLHS, DL);
654
+ Value *PtrBase ;
655
+ APInt Offset ;
656
+ std::tie (PtrBase, Offset ) = getAsConstantIndexedAddress (GEPLHS, DL);
681
657
682
658
// The set of nodes that will take part in this transformation.
683
659
SetVector<Value *> Nodes;
684
660
685
- if (!canRewriteGEPAsOffset (ElemTy, RHS, PtrBase, DL, Nodes))
661
+ if (!canRewriteGEPAsOffset (RHS, PtrBase, DL, Nodes))
686
662
return nullptr ;
687
663
688
664
// We know we can re-write this as
@@ -691,13 +667,14 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
691
667
// can't have overflow on either side. We can therefore re-write
692
668
// this as:
693
669
// OFFSET1 cmp OFFSET2
694
- Value *NewRHS = rewriteGEPAsOffset (ElemTy, RHS, PtrBase, DL, Nodes, IC);
670
+ Value *NewRHS = rewriteGEPAsOffset (RHS, PtrBase, DL, Nodes, IC);
695
671
696
672
// RewriteGEPAsOffset has replaced RHS and all of its uses with a re-written
697
673
// GEP having PtrBase as the pointer base, and has returned in NewRHS the
698
674
// offset. Since Index is the offset of LHS to the base pointer, we will now
699
675
// compare the offsets instead of comparing the pointers.
700
- return new ICmpInst (ICmpInst::getSignedPredicate (Cond), Index, NewRHS);
676
+ return new ICmpInst (ICmpInst::getSignedPredicate (Cond),
677
+ IC.Builder .getInt (Offset), NewRHS);
701
678
}
702
679
703
680
// / Fold comparisons between a GEP instruction and something else. At this point
0 commit comments