[llvm] [FMV][GlobalOpt] Bypass the IFunc Resolver of MultiVersioned functions. (PR #87939)
Jon Roelofs via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 8 08:50:26 PDT 2024
================
@@ -2462,6 +2462,228 @@ DeleteDeadIFuncs(Module &M,
return Changed;
}
+static Function *foldResolverForCallSite(CallBase *CS, uint64_t Priority,
+ TargetTransformInfo &TTI) {
+ // Look for the instruction which feeds the feature mask to the users.
+ auto findRoot = [&TTI](Function *F) -> Instruction * {
+ for (Instruction &I : F->getEntryBlock())
+ if (auto *Load = dyn_cast<LoadInst>(&I))
+ if (Load->getPointerOperand() == TTI.getCPUFeatures(*F->getParent()))
+ return Load;
+ return nullptr;
+ };
+
+ auto *IF = cast<GlobalIFunc>(CS->getCalledOperand());
+ Instruction *Root = findRoot(IF->getResolverFunction());
+ // There is no such instruction. Bail.
+ if (!Root)
+ return nullptr;
+
+ // Create a constant mask to use as seed for the constant propagation.
+ Constant *Seed = Constant::getIntegerValue(
+ Root->getType(), APInt(Root->getType()->getIntegerBitWidth(), Priority));
+
+ auto DL = CS->getModule()->getDataLayout();
+
+ // Recursively propagate on single use chains.
+ std::function<Constant *(Instruction *, Instruction *, Constant *,
+ BasicBlock *)>
+ constFoldInst = [&](Instruction *I, Instruction *Use, Constant *C,
+ BasicBlock *Pred) -> Constant * {
+ // Base case.
+ if (auto *Ret = dyn_cast<ReturnInst>(I))
+ if (Ret->getReturnValue() == Use)
+ return C;
+
+ // Minimal set of instruction types to handle.
+ if (auto *BinOp = dyn_cast<BinaryOperator>(I)) {
+ bool Swap = BinOp->getOperand(1) == Use;
+ if (auto *Other = dyn_cast<Constant>(BinOp->getOperand(Swap ? 0 : 1)))
+ C = Swap ? ConstantFoldBinaryInstruction(BinOp->getOpcode(), Other, C)
+ : ConstantFoldBinaryInstruction(BinOp->getOpcode(), C, Other);
+ } else if (auto *Cmp = dyn_cast<CmpInst>(I)) {
+ bool Swap = Cmp->getOperand(1) == Use;
+ if (auto *Other = dyn_cast<Constant>(Cmp->getOperand(Swap ? 0 : 1)))
+ C = Swap ? ConstantFoldCompareInstOperands(Cmp->getPredicate(), Other,
+ C, DL)
+ : ConstantFoldCompareInstOperands(Cmp->getPredicate(), C,
+ Other, DL);
+ } else if (auto *Sel = dyn_cast<SelectInst>(I)) {
+ if (Sel->getCondition() == Use)
+ C = dyn_cast<Constant>(C->isZeroValue() ? Sel->getFalseValue()
+ : Sel->getTrueValue());
+ } else if (auto *Phi = dyn_cast<PHINode>(I)) {
+ if (Pred)
+ C = dyn_cast<Constant>(Phi->getIncomingValueForBlock(Pred));
+ } else if (auto *Br = dyn_cast<BranchInst>(I)) {
+ if (Br->getCondition() == Use) {
+ BasicBlock *BB = Br->getSuccessor(C->isZeroValue());
+ return constFoldInst(&BB->front(), Root, Seed, Br->getParent());
+ }
+ } else {
+ // Don't know how to handle. Bail.
----------------
jroelofs wrote:
ok
https://github.com/llvm/llvm-project/pull/87939
More information about the llvm-commits
mailing list