@@ -63,6 +63,10 @@ llvm::cl::opt<bool> EnzymePrintType("enzyme-print-type", cl::init(false),
63
63
llvm::cl::opt<bool > RustTypeRules (" enzyme-rust-type" , cl::init(false ),
64
64
cl::Hidden,
65
65
cl::desc(" Enable rust-specific type rules" ));
66
+
67
+ llvm::cl::opt<bool > EnzymeStrictAliasing (
68
+ " enzyme-strict-aliasing" , cl::init(true ), cl::Hidden,
69
+ cl::desc(" Assume strict aliasing of types / type stability" ));
66
70
}
67
71
68
72
const std::map<std::string, llvm::Intrinsic::ID> LIBM_FUNCTIONS = {
@@ -149,6 +153,7 @@ TypeAnalyzer::TypeAnalyzer(const FnTypeInfo &fn, TypeAnalysis &TA,
149
153
: notForAnalysis(getGuaranteedUnreachable(fn.Function)), intseen(),
150
154
fntypeinfo(fn), interprocedural(TA), direction(direction), Invalid(false ),
151
155
PHIRecur(false ), DT(std::make_shared<DominatorTree>(*fn.Function)),
156
+ PDT(std::make_shared<PostDominatorTree>(*fn.Function)),
152
157
LI(std::make_shared<LoopInfo>(*DT)) {
153
158
154
159
assert (fntypeinfo.KnownValues .size () ==
@@ -176,11 +181,12 @@ TypeAnalyzer::TypeAnalyzer(const FnTypeInfo &fn, TypeAnalysis &TA,
176
181
TypeAnalyzer::TypeAnalyzer (
177
182
const FnTypeInfo &fn, TypeAnalysis &TA,
178
183
const llvm::SmallPtrSetImpl<llvm::BasicBlock *> ¬ForAnalysis,
179
- std::shared_ptr<llvm::DominatorTree> DT, std::shared_ptr<llvm::LoopInfo> LI,
180
- uint8_t direction, bool PHIRecur)
184
+ std::shared_ptr<llvm::DominatorTree> DT,
185
+ std::shared_ptr<llvm::PostDominatorTree> PDT,
186
+ std::shared_ptr<llvm::LoopInfo> LI, uint8_t direction, bool PHIRecur)
181
187
: notForAnalysis(notForAnalysis.begin(), notForAnalysis.end()), intseen(),
182
188
fntypeinfo(fn), interprocedural(TA), direction(direction), Invalid(false ),
183
- PHIRecur(PHIRecur), DT(DT), LI(LI) {
189
+ PHIRecur(PHIRecur), DT(DT), PDT(PDT), LI(LI) {
184
190
assert (fntypeinfo.KnownValues .size () ==
185
191
fntypeinfo.Function ->getFunctionType ()->getNumParams ());
186
192
}
@@ -402,7 +408,7 @@ void getConstantAnalysis(Constant *Val, TypeAnalyzer &TA,
402
408
// Just analyze this new "instruction" and none of the others
403
409
{
404
410
TypeAnalyzer tmpAnalysis (TA.fntypeinfo , TA.interprocedural ,
405
- TA.notForAnalysis , TA.DT , TA.LI );
411
+ TA.notForAnalysis , TA.DT , TA.PDT , TA. LI );
406
412
tmpAnalysis.visit (*I);
407
413
analysis[Val] = tmpAnalysis.getAnalysis (I);
408
414
}
@@ -548,8 +554,32 @@ void TypeAnalyzer::updateAnalysis(Value *Val, TypeTree Data, Value *Origin) {
548
554
llvm::errs () << " inst: " << *I << " \n " ;
549
555
}
550
556
assert (fntypeinfo.Function == I->getParent ()->getParent ());
551
- } else if (auto Arg = dyn_cast<Argument>(Val))
557
+ assert (Origin);
558
+ if (!EnzymeStrictAliasing) {
559
+ if (auto OI = dyn_cast<Instruction>(Origin)) {
560
+ if (OI->getParent () != I->getParent () &&
561
+ !PDT->dominates (OI->getParent (), I->getParent ())) {
562
+ if (EnzymePrintType)
563
+ llvm::errs () << " skipping update into " << *I << " of "
564
+ << Data.str () << " from " << *OI << " \n " ;
565
+ return ;
566
+ }
567
+ }
568
+ }
569
+ } else if (auto Arg = dyn_cast<Argument>(Val)) {
552
570
assert (fntypeinfo.Function == Arg->getParent ());
571
+ if (!EnzymeStrictAliasing)
572
+ if (auto OI = dyn_cast<Instruction>(Origin)) {
573
+ auto I = &*fntypeinfo.Function ->getEntryBlock ().begin ();
574
+ if (OI->getParent () != I->getParent () &&
575
+ !PDT->dominates (OI->getParent (), I->getParent ())) {
576
+ if (EnzymePrintType)
577
+ llvm::errs () << " skipping update into " << *Arg << " of "
578
+ << Data.str () << " from " << *OI << " \n " ;
579
+ return ;
580
+ }
581
+ }
582
+ }
553
583
554
584
// Attempt to update the underlying analysis
555
585
bool LegalOr = true ;
@@ -641,7 +671,7 @@ void TypeAnalyzer::prepareArgs() {
641
671
// Propagate input type information for arguments
642
672
for (auto &pair : fntypeinfo.Arguments ) {
643
673
assert (pair.first ->getParent () == fntypeinfo.Function );
644
- updateAnalysis (pair.first , pair.second , nullptr );
674
+ updateAnalysis (pair.first , pair.second , pair. first );
645
675
}
646
676
647
677
// Get type and other information about argument
@@ -656,7 +686,7 @@ void TypeAnalyzer::prepareArgs() {
656
686
for (Instruction &I : BB) {
657
687
if (ReturnInst *RI = dyn_cast<ReturnInst>(&I)) {
658
688
if (Value *RV = RI->getReturnValue ()) {
659
- updateAnalysis (RV, fntypeinfo.Return , nullptr );
689
+ updateAnalysis (RV, fntypeinfo.Return , RV );
660
690
updateAnalysis (RV, getAnalysis (RV), RV);
661
691
}
662
692
}
@@ -852,7 +882,7 @@ void TypeAnalyzer::runPHIHypotheses() {
852
882
// the incoming operands are integral
853
883
854
884
TypeAnalyzer tmpAnalysis (fntypeinfo, interprocedural,
855
- notForAnalysis, DT, LI, DOWN,
885
+ notForAnalysis, DT, PDT, LI, DOWN,
856
886
/* PHIRecur*/ true );
857
887
tmpAnalysis.intseen = intseen;
858
888
tmpAnalysis.analysis = analysis;
@@ -884,7 +914,7 @@ void TypeAnalyzer::runPHIHypotheses() {
884
914
// Assume that this is an integer, does that mean we can prove that
885
915
// the incoming operands are integral
886
916
TypeAnalyzer tmpAnalysis (fntypeinfo, interprocedural,
887
- notForAnalysis, DT, LI, DOWN,
917
+ notForAnalysis, DT, PDT, LI, DOWN,
888
918
/* PHIRecur*/ true );
889
919
tmpAnalysis.intseen = intseen;
890
920
tmpAnalysis.analysis = analysis;
0 commit comments