Skip to content

Commit 51482db

Browse files
committed
Speed up constantexpr type analysis
1 parent 4f1e195 commit 51482db

File tree

1 file changed

+99
-1
lines changed

1 file changed

+99
-1
lines changed

enzyme/Enzyme/TypeAnalysis/TypeAnalysis.cpp

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,37 @@ TypeTree getConstantAnalysis(Constant *Val, TypeAnalyzer &TA) {
331331
// ConstantExprs are handled by considering the
332332
// equivalent instruction
333333
if (auto CE = dyn_cast<ConstantExpr>(Val)) {
334+
if (CE->isCast()) {
335+
if (CE->getType()->isPointerTy() && isa<ConstantInt>(CE->getOperand(0)))
336+
return TypeTree(BaseType::Anything).Only(-1);
337+
return getConstantAnalysis(CE->getOperand(0), TA);
338+
}
339+
if (CE->isGEPWithNoNotionalOverIndexing()) {
340+
auto gepData0 = getConstantAnalysis(CE->getOperand(0), TA).Data0();
341+
342+
auto g2 = cast<GetElementPtrInst>(CE->getAsInstruction());
343+
#if LLVM_VERSION_MAJOR > 6
344+
APInt ai(DL.getIndexSizeInBits(g2->getPointerAddressSpace()), 0);
345+
#else
346+
APInt ai(DL.getPointerSize(g2->getPointerAddressSpace()) * 8, 0);
347+
#endif
348+
g2->accumulateConstantOffset(DL, ai);
349+
// Using destructor rather than eraseFromParent
350+
// as g2 has no parent
351+
delete g2;
352+
353+
int off = (int)ai.getLimitedValue();
354+
355+
// TODO also allow negative offsets
356+
if (off < 0)
357+
return TypeTree(BaseType::Pointer).Only(-1);
358+
359+
TypeTree result =
360+
gepData0.ShiftIndices(DL, /*init offset*/ off, /*max size*/ -1,
361+
/*new offset*/ 0);
362+
result.insert({}, BaseType::Pointer);
363+
return result.Only(-1);
364+
}
334365
TypeTree Result;
335366

336367
auto I = CE->getAsInstruction();
@@ -389,6 +420,8 @@ TypeTree TypeAnalyzer::getAnalysis(Value *Val) {
389420
if (auto found = findInMap(analysis, Val)) {
390421
result |= *found;
391422
*found = result;
423+
} else {
424+
analysis[Val] = result;
392425
}
393426
return result;
394427
}
@@ -481,7 +514,10 @@ void TypeAnalyzer::updateAnalysis(Value *Val, TypeTree Data, Value *Origin) {
481514

482515
// Attempt to update the underlying analysis
483516
bool LegalOr = true;
484-
auto prev = analysis[Val];
517+
if (analysis.find(Val) == analysis.end() && isa<Constant>(Val))
518+
analysis[Val] = getConstantAnalysis(cast<Constant>(Val), *this);
519+
520+
TypeTree prev = analysis[Val];
485521
bool Changed =
486522
analysis[Val].checkedOrIn(Data, /*PointerIntSame*/ false, LegalOr);
487523

@@ -906,6 +942,68 @@ void TypeAnalyzer::visitValue(Value &val) {
906942
}
907943

908944
void TypeAnalyzer::visitConstantExpr(ConstantExpr &CE) {
945+
if (CE.isCast()) {
946+
if (direction & DOWN)
947+
updateAnalysis(&CE, getAnalysis(CE.getOperand(0)), &CE);
948+
if (direction & UP)
949+
updateAnalysis(CE.getOperand(0), getAnalysis(&CE), &CE);
950+
return;
951+
}
952+
if (CE.isGEPWithNoNotionalOverIndexing()) {
953+
954+
auto &DL = fntypeinfo.Function->getParent()->getDataLayout();
955+
auto g2 = cast<GetElementPtrInst>(CE.getAsInstruction());
956+
#if LLVM_VERSION_MAJOR > 6
957+
APInt ai(DL.getIndexSizeInBits(g2->getPointerAddressSpace()), 0);
958+
#else
959+
APInt ai(DL.getPointerSize(g2->getPointerAddressSpace()) * 8, 0);
960+
#endif
961+
g2->accumulateConstantOffset(DL, ai);
962+
// Using destructor rather than eraseFromParent
963+
// as g2 has no parent
964+
965+
int maxSize = -1;
966+
if (cast<ConstantInt>(CE.getOperand(1))->getLimitedValue() == 0) {
967+
maxSize = DL.getTypeAllocSizeInBits(
968+
cast<PointerType>(g2->getType())->getElementType()) /
969+
8;
970+
}
971+
972+
delete g2;
973+
974+
int off = (int)ai.getLimitedValue();
975+
976+
// TODO also allow negative offsets
977+
if (off < 0) {
978+
if (direction & DOWN)
979+
updateAnalysis(&CE, TypeTree(BaseType::Pointer).Only(-1), &CE);
980+
if (direction & UP)
981+
updateAnalysis(CE.getOperand(0), TypeTree(BaseType::Pointer).Only(-1),
982+
&CE);
983+
return;
984+
}
985+
986+
if (direction & DOWN) {
987+
auto gepData0 = getAnalysis(CE.getOperand(0)).Data0();
988+
TypeTree result =
989+
gepData0.ShiftIndices(DL, /*init offset*/ off,
990+
/*max size*/ maxSize, /*newoffset*/ 0);
991+
result.insert({}, BaseType::Pointer);
992+
updateAnalysis(&CE, result.Only(-1), &CE);
993+
}
994+
if (direction & UP) {
995+
auto pointerData0 = getAnalysis(&CE).Data0();
996+
997+
TypeTree result =
998+
pointerData0.ShiftIndices(DL, /*init offset*/ 0, /*max size*/ -1,
999+
/*new offset*/ off);
1000+
result.insert({}, BaseType::Pointer);
1001+
llvm::errs() << "CE: " << CE << " pdata0: " << pointerData0.str()
1002+
<< " off: " << off << " res: " << result.str() << "\n";
1003+
updateAnalysis(CE.getOperand(0), result.Only(-1), &CE);
1004+
}
1005+
return;
1006+
}
9091007
auto I = CE.getAsInstruction();
9101008
I->insertBefore(fntypeinfo.Function->getEntryBlock().getTerminator());
9111009
analysis[I] = analysis[&CE];

0 commit comments

Comments
 (0)