215
215
#include " llvm/IR/Metadata.h"
216
216
#include " llvm/IR/Operator.h"
217
217
#include " llvm/IR/PatternMatch.h"
218
+ #include " llvm/IR/ReplaceConstant.h"
218
219
#include " llvm/InitializePasses.h"
219
220
#include " llvm/Pass.h"
220
221
#include " llvm/Support/AtomicOrdering.h"
@@ -579,18 +580,14 @@ bool StoreFatPtrsAsIntsVisitor::visitStoreInst(StoreInst &SI) {
579
580
// / buffer fat pointer constant.
580
581
static std::pair<Constant *, Constant *>
581
582
splitLoweredFatBufferConst (Constant *C) {
582
- if (auto *AZ = dyn_cast<ConstantAggregateZero>(C))
583
- return std::make_pair (AZ->getStructElement (0 ), AZ->getStructElement (1 ));
584
- if (auto *SC = dyn_cast<ConstantStruct>(C))
585
- return std::make_pair (SC->getOperand (0 ), SC->getOperand (1 ));
586
- llvm_unreachable (" Conversion should've created a {p8, i32} struct" );
583
+ assert (isSplitFatPtr (C->getType ()) && " Not a split fat buffer pointer" );
584
+ return std::make_pair (C->getAggregateElement (0u ), C->getAggregateElement (1u ));
587
585
}
588
586
589
587
namespace {
590
588
// / Handle the remapping of ptr addrspace(7) constants.
591
589
class FatPtrConstMaterializer final : public ValueMaterializer {
592
590
BufferFatPtrToStructTypeMap *TypeMap;
593
- BufferFatPtrToIntTypeMap *IntTypeMap;
594
591
// An internal mapper that is used to recurse into the arguments of constants.
595
592
// While the documentation for `ValueMapper` specifies not to use it
596
593
// recursively, examination of the logic in mapValue() shows that it can
@@ -600,16 +597,12 @@ class FatPtrConstMaterializer final : public ValueMaterializer {
600
597
601
598
Constant *materializeBufferFatPtrConst (Constant *C);
602
599
603
- const DataLayout &DL;
604
-
605
600
public:
606
601
// UnderlyingMap is the value map this materializer will be filling.
607
602
FatPtrConstMaterializer (BufferFatPtrToStructTypeMap *TypeMap,
608
- ValueToValueMapTy &UnderlyingMap,
609
- BufferFatPtrToIntTypeMap *IntTypeMap,
610
- const DataLayout &DL)
611
- : TypeMap(TypeMap), IntTypeMap(IntTypeMap),
612
- InternalMapper (UnderlyingMap, RF_None, TypeMap, this ), DL(DL) {}
603
+ ValueToValueMapTy &UnderlyingMap)
604
+ : TypeMap(TypeMap),
605
+ InternalMapper (UnderlyingMap, RF_None, TypeMap, this ) {}
613
606
virtual ~FatPtrConstMaterializer () = default ;
614
607
615
608
Value *materialize (Value *V) override ;
@@ -632,10 +625,6 @@ Constant *FatPtrConstMaterializer::materializeBufferFatPtrConst(Constant *C) {
632
625
UndefValue::get (NewTy->getElementType (1 ))});
633
626
}
634
627
635
- if (isa<GlobalValue>(C))
636
- report_fatal_error (" Global values containing ptr addrspace(7) (buffer "
637
- " fat pointer) values are not supported" );
638
-
639
628
if (auto *VC = dyn_cast<ConstantVector>(C)) {
640
629
if (Constant *S = VC->getSplatValue ()) {
641
630
Constant *NewS = InternalMapper.mapConstant (*S);
@@ -661,147 +650,21 @@ Constant *FatPtrConstMaterializer::materializeBufferFatPtrConst(Constant *C) {
661
650
return ConstantStruct::get (NewTy, {RsrcVec, OffVec});
662
651
}
663
652
664
- // Constant expressions. This code mirrors how we fix up the equivalent
665
- // instructions later.
666
- auto *CE = dyn_cast<ConstantExpr>(C);
667
- if (!CE)
668
- return nullptr ;
669
- if (auto *GEPO = dyn_cast<GEPOperator>(C)) {
670
- Constant *RemappedPtr =
671
- InternalMapper.mapConstant (*cast<Constant>(GEPO->getPointerOperand ()));
672
- auto [Rsrc, Off] = splitLoweredFatBufferConst (RemappedPtr);
673
- Type *OffTy = Off->getType ();
674
- bool InBounds = GEPO->isInBounds ();
675
-
676
- MapVector<Value *, APInt> VariableOffs;
677
- APInt NewConstOffVal = APInt::getZero (BufferOffsetWidth);
678
- if (!GEPO->collectOffset (DL, BufferOffsetWidth, VariableOffs,
679
- NewConstOffVal))
680
- report_fatal_error (
681
- " Scalable vector or unsized struct in fat pointer GEP" );
682
- Constant *OffAccum = nullptr ;
683
- for (auto [Arg, Multiple] : VariableOffs) {
684
- Constant *NewArg = InternalMapper.mapConstant (*cast<Constant>(Arg));
685
- NewArg = ConstantFoldIntegerCast (NewArg, OffTy, /* IsSigned=*/ true , DL);
686
- if (!Multiple.isOne ()) {
687
- if (Multiple.isPowerOf2 ()) {
688
- NewArg = ConstantExpr::getShl (
689
- NewArg, CE->getIntegerValue (OffTy, APInt (BufferOffsetWidth,
690
- Multiple.logBase2 ())));
691
- } else {
692
- NewArg = ConstantExpr::getMul (NewArg,
693
- CE->getIntegerValue (OffTy, Multiple));
694
- }
695
- }
696
- if (OffAccum) {
697
- OffAccum = ConstantExpr::getAdd (OffAccum, NewArg);
698
- } else {
699
- OffAccum = NewArg;
700
- }
701
- }
702
- Constant *NewConstOff = CE->getIntegerValue (OffTy, NewConstOffVal);
703
- if (OffAccum)
704
- OffAccum = ConstantExpr::getAdd (OffAccum, NewConstOff);
705
- else
706
- OffAccum = NewConstOff;
707
- bool HasNonNegativeOff = false ;
708
- if (auto *CI = dyn_cast<ConstantInt>(OffAccum)) {
709
- HasNonNegativeOff = !CI->isNegative ();
710
- }
711
- Constant *NewOff = ConstantExpr::getAdd (
712
- Off, OffAccum, /* hasNUW=*/ InBounds && HasNonNegativeOff,
713
- /* hasNSW=*/ false );
714
- return ConstantStruct::get (NewTy, {Rsrc, NewOff});
715
- }
716
-
717
- if (auto *PI = dyn_cast<PtrToIntOperator>(CE)) {
718
- Constant *Parts =
719
- InternalMapper.mapConstant (*cast<Constant>(PI->getPointerOperand ()));
720
- auto [Rsrc, Off] = splitLoweredFatBufferConst (Parts);
721
- // Here, we take advantage of the fact that ptrtoint has a built-in
722
- // zero-extension behavior.
723
- unsigned FatPtrWidth =
724
- DL.getPointerSizeInBits (AMDGPUAS::BUFFER_FAT_POINTER);
725
- Constant *RsrcInt = CE->getPtrToInt (Rsrc, SrcTy);
726
- unsigned Width = SrcTy->getScalarSizeInBits ();
727
- Constant *Shift =
728
- CE->getIntegerValue (SrcTy, APInt (Width, BufferOffsetWidth));
729
- Constant *OffCast =
730
- ConstantFoldIntegerCast (Off, SrcTy, /* IsSigned=*/ false , DL);
731
- Constant *RsrcHi = ConstantExpr::getShl (
732
- RsrcInt, Shift, Width >= FatPtrWidth, Width > FatPtrWidth);
733
- // This should be an or, but those got recently removed.
734
- Constant *Result = ConstantExpr::getAdd (RsrcHi, OffCast, true , true );
735
- return Result;
736
- }
653
+ if (isa<GlobalValue>(C))
654
+ report_fatal_error (" Global values containing ptr addrspace(7) (buffer "
655
+ " fat pointer) values are not supported" );
737
656
738
- if (CE->getOpcode () == Instruction::IntToPtr) {
739
- auto *Arg = cast<Constant>(CE->getOperand (0 ));
740
- unsigned FatPtrWidth =
741
- DL.getPointerSizeInBits (AMDGPUAS::BUFFER_FAT_POINTER);
742
- unsigned RsrcPtrWidth = DL.getPointerSizeInBits (AMDGPUAS::BUFFER_RESOURCE);
743
- auto *WantedTy = Arg->getType ()->getWithNewBitWidth (FatPtrWidth);
744
- Arg = ConstantFoldIntegerCast (Arg, WantedTy, /* IsSigned=*/ false , DL);
745
-
746
- Constant *Shift =
747
- CE->getIntegerValue (WantedTy, APInt (FatPtrWidth, BufferOffsetWidth));
748
- Type *RsrcIntType = WantedTy->getWithNewBitWidth (RsrcPtrWidth);
749
- Type *RsrcTy = NewTy->getElementType (0 );
750
- Type *OffTy = WantedTy->getWithNewBitWidth (BufferOffsetWidth);
751
- Constant *RsrcInt = CE->getTrunc (
752
- ConstantFoldBinaryOpOperands (Instruction::LShr, Arg, Shift, DL),
753
- RsrcIntType);
754
- Constant *Rsrc = CE->getIntToPtr (RsrcInt, RsrcTy);
755
- Constant *Off = ConstantFoldIntegerCast (Arg, OffTy, /* isSigned=*/ false , DL);
756
-
757
- return ConstantStruct::get (NewTy, {Rsrc, Off});
758
- }
657
+ if (isa<ConstantExpr>(C))
658
+ report_fatal_error (" Constant exprs containing ptr addrspace(7) (buffer "
659
+ " fat pointer) values should have been expanded earlier" );
759
660
760
- if (auto *AC = dyn_cast<AddrSpaceCastOperator>(CE)) {
761
- unsigned SrcAS = AC->getSrcAddressSpace ();
762
- unsigned DstAS = AC->getDestAddressSpace ();
763
- auto *Arg = cast<Constant>(AC->getPointerOperand ());
764
- auto *NewArg = InternalMapper.mapConstant (*Arg);
765
- if (!NewArg)
766
- return nullptr ;
767
- if (SrcAS == AMDGPUAS::BUFFER_FAT_POINTER &&
768
- DstAS == AMDGPUAS::BUFFER_FAT_POINTER)
769
- return NewArg;
770
- if (SrcAS == AMDGPUAS::BUFFER_RESOURCE &&
771
- DstAS == AMDGPUAS::BUFFER_FAT_POINTER) {
772
- auto *NullOff = CE->getNullValue (NewTy->getElementType (1 ));
773
- return ConstantStruct::get (NewTy, {NewArg, NullOff});
774
- }
775
- report_fatal_error (
776
- " Unsupported address space cast for a buffer fat pointer" );
777
- }
778
661
return nullptr ;
779
662
}
780
663
781
664
Value *FatPtrConstMaterializer::materialize (Value *V) {
782
665
Constant *C = dyn_cast<Constant>(V);
783
666
if (!C)
784
667
return nullptr ;
785
- if (auto *GEPO = dyn_cast<GEPOperator>(C)) {
786
- // As a special case, adjust GEP constants that have a ptr addrspace(7) in
787
- // their source types here, since the earlier local changes didn't handle
788
- // htis.
789
- Type *SrcTy = GEPO->getSourceElementType ();
790
- Type *NewSrcTy = IntTypeMap->remapType (SrcTy);
791
- if (SrcTy != NewSrcTy) {
792
- SmallVector<Constant *> Ops;
793
- Ops.reserve (GEPO->getNumOperands ());
794
- for (const Use &U : GEPO->operands ())
795
- Ops.push_back (cast<Constant>(U.get ()));
796
- auto *NewGEP = ConstantExpr::getGetElementPtr (
797
- NewSrcTy, Ops[0 ], ArrayRef<Constant *>(Ops).slice (1 ),
798
- GEPO->getNoWrapFlags (), GEPO->getInRange ());
799
- LLVM_DEBUG (dbgs () << " p7-getting GEP: " << *GEPO << " becomes " << *NewGEP
800
- << " \n " );
801
- Value *FurtherMap = materialize (NewGEP);
802
- return FurtherMap ? FurtherMap : NewGEP;
803
- }
804
- }
805
668
// Structs and other types that happen to contain fat pointers get remapped
806
669
// by the mapValue() logic.
807
670
if (!isBufferFatPtrConst (C))
@@ -1782,14 +1645,9 @@ class AMDGPULowerBufferFatPointers : public ModulePass {
1782
1645
static bool containsBufferFatPointers (const Function &F,
1783
1646
BufferFatPtrToStructTypeMap *TypeMap) {
1784
1647
bool HasFatPointers = false ;
1785
- for (const BasicBlock &BB : F) {
1786
- for (const Instruction &I : BB) {
1648
+ for (const BasicBlock &BB : F)
1649
+ for (const Instruction &I : BB)
1787
1650
HasFatPointers |= (I.getType () != TypeMap->remapType (I.getType ()));
1788
- for (const Use &U : I.operands ())
1789
- if (auto *C = dyn_cast<Constant>(U.get ()))
1790
- HasFatPointers |= isBufferFatPtrConst (C);
1791
- }
1792
- }
1793
1651
return HasFatPointers;
1794
1652
}
1795
1653
@@ -1888,6 +1746,36 @@ bool AMDGPULowerBufferFatPointers::run(Module &M, const TargetMachine &TM) {
1888
1746
" buffer resource pointers (address space 8) instead." );
1889
1747
}
1890
1748
1749
+ {
1750
+ // Collect all constant exprs and aggregates referenced by any function.
1751
+ SmallVector<Constant *, 8 > Worklist;
1752
+ for (Function &F : M.functions ())
1753
+ for (Instruction &I : instructions (F))
1754
+ for (Value *Op : I.operands ())
1755
+ if (isa<ConstantExpr>(Op) || isa<ConstantAggregate>(Op))
1756
+ Worklist.push_back (cast<Constant>(Op));
1757
+
1758
+ // Recursively look for any referenced buffer pointer constants.
1759
+ SmallPtrSet<Constant *, 8 > Visited;
1760
+ SetVector<Constant *> BufferFatPtrConsts;
1761
+ while (!Worklist.empty ()) {
1762
+ Constant *C = Worklist.pop_back_val ();
1763
+ if (!Visited.insert (C).second )
1764
+ continue ;
1765
+ if (isBufferFatPtrOrVector (C->getType ()))
1766
+ BufferFatPtrConsts.insert (C);
1767
+ for (Value *Op : C->operands ())
1768
+ if (isa<ConstantExpr>(Op) || isa<ConstantAggregate>(Op))
1769
+ Worklist.push_back (cast<Constant>(Op));
1770
+ }
1771
+
1772
+ // Expand all constant expressions using fat buffer pointers to
1773
+ // instructions.
1774
+ Changed |= convertUsersOfConstantsToInstructions (
1775
+ BufferFatPtrConsts.getArrayRef (), /* RestrictToFunc=*/ nullptr ,
1776
+ /* RemoveDeadConstants=*/ false , /* IncludeSelf=*/ true );
1777
+ }
1778
+
1891
1779
StoreFatPtrsAsIntsVisitor MemOpsRewrite (&IntTM, M.getContext ());
1892
1780
for (Function &F : M.functions ()) {
1893
1781
bool InterfaceChange = hasFatPointerInterface (F, &StructTM);
@@ -1903,7 +1791,7 @@ bool AMDGPULowerBufferFatPointers::run(Module &M, const TargetMachine &TM) {
1903
1791
SmallVector<Function *> Intrinsics;
1904
1792
// Keep one big map so as to memoize constants across functions.
1905
1793
ValueToValueMapTy CloneMap;
1906
- FatPtrConstMaterializer Materializer (&StructTM, CloneMap, &IntTM, DL );
1794
+ FatPtrConstMaterializer Materializer (&StructTM, CloneMap);
1907
1795
1908
1796
ValueMapper LowerInFuncs (CloneMap, RF_None, &StructTM, &Materializer);
1909
1797
for (auto [F, InterfaceChange] : NeedsRemap) {
0 commit comments