@@ -853,7 +853,7 @@ bool hasInitializesAttr(Instruction *I) {
853853
854854struct ArgumentInitInfo {
855855 unsigned Idx;
856- bool HasDeadOnUnwindAttr ;
856+ bool IsDeadOnUnwind ;
857857 ConstantRangeList Inits;
858858};
859859
@@ -869,89 +869,19 @@ ConstantRangeList getIntersectedInitRangeList(ArrayRef<ArgumentInitInfo> Args,
869869 // To address unwind, the function should have nounwind attribute or the
870870 // arguments have dead_on_unwind attribute. Otherwise, return empty.
871871 for (const auto &Arg : Args) {
872- if (!CallHasNoUnwindAttr && !Arg.HasDeadOnUnwindAttr )
872+ if (!CallHasNoUnwindAttr && !Arg.IsDeadOnUnwind )
873873 return {};
874874 if (Arg.Inits .empty ())
875875 return {};
876876 }
877877
878- if (Args.size () == 1 )
879- return Args[0 ].Inits ;
880-
881878 ConstantRangeList IntersectedIntervals = Args.front ().Inits ;
882879 for (auto &Arg : Args.drop_front ())
883880 IntersectedIntervals = IntersectedIntervals.intersectWith (Arg.Inits );
884881
885882 return IntersectedIntervals;
886883}
887884
888- // Return the locations written by the initializes attribute.
889- // Note that this function considers:
890- // 1. Unwind edge: apply "initializes" attribute only if the callee has
891- // "nounwind" attribute or the argument has "dead_on_unwind" attribute.
892- // 2. Argument alias: for aliasing arguments, the "initializes" attribute is
893- // the intersected range list of their "initializes" attributes.
894- SmallVector<MemoryLocation, 1 >
895- getInitializesArgMemLoc (const Instruction *I, BatchAAResults &BatchAA) {
896- const CallBase *CB = dyn_cast<CallBase>(I);
897- if (!CB)
898- return {};
899-
900- // Collect aliasing arguments and their initializes ranges.
901- SmallMapVector<Value *, SmallVector<ArgumentInitInfo, 2 >, 2 > Arguments;
902- for (unsigned Idx = 0 , Count = CB->arg_size (); Idx < Count; ++Idx) {
903- ConstantRangeList Inits;
904- Attribute InitializesAttr = CB->getParamAttr (Idx, Attribute::Initializes);
905- if (InitializesAttr.isValid ())
906- Inits = InitializesAttr.getValueAsConstantRangeList ();
907-
908- bool HasDeadOnUnwindAttr = CB->paramHasAttr (Idx, Attribute::DeadOnUnwind);
909- ArgumentInitInfo InitInfo{Idx, HasDeadOnUnwindAttr, Inits};
910- Value *CurArg = CB->getArgOperand (Idx);
911- bool FoundAliasing = false ;
912- for (auto &[Arg, AliasList] : Arguments) {
913- auto AAR = BatchAA.alias (MemoryLocation::getBeforeOrAfter (Arg),
914- MemoryLocation::getBeforeOrAfter (CurArg));
915- if (AAR == AliasResult::NoAlias) {
916- continue ;
917- } else if (AAR == AliasResult::MustAlias) {
918- FoundAliasing = true ;
919- AliasList.push_back (InitInfo);
920- } else {
921- // For PartialAlias and MayAlias, there is an offset or may be an
922- // unknown offset between the arguments and we insert an empty init
923- // range to discard the entire initializes info while intersecting.
924- FoundAliasing = true ;
925- AliasList.push_back (
926- ArgumentInitInfo{Idx, HasDeadOnUnwindAttr, ConstantRangeList ()});
927- }
928- }
929- if (!FoundAliasing)
930- Arguments[CurArg] = {InitInfo};
931- }
932-
933- SmallVector<MemoryLocation, 1 > Locations;
934- for (const auto &[_, Args] : Arguments) {
935- auto IntersectedRanges =
936- getIntersectedInitRangeList (Args, CB->doesNotThrow ());
937- if (IntersectedRanges.empty ())
938- continue ;
939-
940- for (const auto &Arg : Args) {
941- for (const auto &Range : IntersectedRanges) {
942- int64_t Start = Range.getLower ().getSExtValue ();
943- int64_t End = Range.getUpper ().getSExtValue ();
944- // For now, we only handle locations starting at offset 0.
945- if (Start == 0 )
946- Locations.push_back (MemoryLocation (CB->getArgOperand (Arg.Idx ),
947- LocationSize::precise (End - Start),
948- CB->getAAMetadata ()));
949- }
950- }
951- }
952- return Locations;
953- }
954-
955885struct DSEState {
956886 Function &F;
957887 AliasAnalysis &AA;
@@ -1281,7 +1211,7 @@ struct DSEState {
12811211 Locations.push_back (std::make_pair (*Loc, false ));
12821212
12831213 if (ConsiderInitializesAttr) {
1284- for (auto &MemLoc : getInitializesArgMemLoc (I, BatchAA )) {
1214+ for (auto &MemLoc : getInitializesArgMemLoc (I)) {
12851215 Locations.push_back (std::make_pair (MemLoc, true ));
12861216 }
12871217 }
@@ -2312,6 +2242,16 @@ struct DSEState {
23122242 return MadeChange;
23132243 }
23142244
2245+ // Return the locations written by the initializes attribute.
2246+ // Note that this function considers:
2247+ // 1. Unwind edge: use "initializes" attribute only if the callee has
2248+ // "nounwind" attribute, or the argument has "dead_on_unwind" attribute,
2249+ // or the argument is invisble to caller on unwind. That is, we don't
2250+ // perform incorrect DSE on unwind edges in the current function.
2251+ // 2. Argument alias: for aliasing arguments, the "initializes" attribute is
2252+ // the intersected range list of their "initializes" attributes.
2253+ SmallVector<MemoryLocation, 1 > getInitializesArgMemLoc (const Instruction *I);
2254+
23152255 // Try to eliminate dead defs that access `KillingLocWrapper.MemLoc` and are
23162256 // killed by `KillingLocWrapper.MemDef`. Return whether
23172257 // any changes were made, and whether `KillingLocWrapper.DefInst` was deleted.
@@ -2323,6 +2263,75 @@ struct DSEState {
23232263 bool eliminateDeadDefs (const MemoryDefWrapper &KillingDefWrapper);
23242264};
23252265
2266+ SmallVector<MemoryLocation, 1 >
2267+ DSEState::getInitializesArgMemLoc (const Instruction *I) {
2268+ const CallBase *CB = dyn_cast<CallBase>(I);
2269+ if (!CB)
2270+ return {};
2271+
2272+ // Collect aliasing arguments and their initializes ranges.
2273+ SmallMapVector<Value *, SmallVector<ArgumentInitInfo, 2 >, 2 > Arguments;
2274+ for (unsigned Idx = 0 , Count = CB->arg_size (); Idx < Count; ++Idx) {
2275+ ConstantRangeList Inits;
2276+ Attribute InitializesAttr = CB->getParamAttr (Idx, Attribute::Initializes);
2277+ if (InitializesAttr.isValid ())
2278+ Inits = InitializesAttr.getValueAsConstantRangeList ();
2279+
2280+ Value *CurArg = CB->getArgOperand (Idx);
2281+ // We don't perform incorrect DSE on unwind edges in the current function,
2282+ // and use the "initialize" attribute to kill dead stores if :
2283+ // - The call does not throw exceptions, "CB->doesNotThrow()".
2284+ // - Or the argument has "dead_on_unwind" attribute.
2285+ // - Or the argument is invisble to caller on unwind, and CB isa<CallInst>
2286+ // which means no unwind edges.
2287+ bool IsDeadOnUnwind =
2288+ CB->paramHasAttr (Idx, Attribute::DeadOnUnwind) ||
2289+ (isInvisibleToCallerOnUnwind (CurArg) && isa<CallInst>(CB));
2290+ ArgumentInitInfo InitInfo{Idx, IsDeadOnUnwind, Inits};
2291+ bool FoundAliasing = false ;
2292+ for (auto &[Arg, AliasList] : Arguments) {
2293+ auto AAR = BatchAA.alias (MemoryLocation::getBeforeOrAfter (Arg),
2294+ MemoryLocation::getBeforeOrAfter (CurArg));
2295+ if (AAR == AliasResult::NoAlias) {
2296+ continue ;
2297+ } else if (AAR == AliasResult::MustAlias) {
2298+ FoundAliasing = true ;
2299+ AliasList.push_back (InitInfo);
2300+ } else {
2301+ // For PartialAlias and MayAlias, there is an offset or may be an
2302+ // unknown offset between the arguments and we insert an empty init
2303+ // range to discard the entire initializes info while intersecting.
2304+ FoundAliasing = true ;
2305+ AliasList.push_back (
2306+ ArgumentInitInfo{Idx, IsDeadOnUnwind, ConstantRangeList ()});
2307+ }
2308+ }
2309+ if (!FoundAliasing)
2310+ Arguments[CurArg] = {InitInfo};
2311+ }
2312+
2313+ SmallVector<MemoryLocation, 1 > Locations;
2314+ for (const auto &[_, Args] : Arguments) {
2315+ auto IntersectedRanges =
2316+ getIntersectedInitRangeList (Args, CB->doesNotThrow ());
2317+ if (IntersectedRanges.empty ())
2318+ continue ;
2319+
2320+ for (const auto &Arg : Args) {
2321+ for (const auto &Range : IntersectedRanges) {
2322+ int64_t Start = Range.getLower ().getSExtValue ();
2323+ int64_t End = Range.getUpper ().getSExtValue ();
2324+ // For now, we only handle locations starting at offset 0.
2325+ if (Start == 0 )
2326+ Locations.push_back (MemoryLocation (CB->getArgOperand (Arg.Idx ),
2327+ LocationSize::precise (End - Start),
2328+ CB->getAAMetadata ()));
2329+ }
2330+ }
2331+ }
2332+ return Locations;
2333+ }
2334+
23262335std::pair<bool , bool >
23272336DSEState::eliminateDeadDefs (const MemoryLocationWrapper &KillingLocWrapper) {
23282337 bool Changed = false ;
0 commit comments