/// argument.
bool isArgumentInteresting(Argument *A,
SmallVectorImpl<CallArgBinding> &Constants) {
-
- // No point in specialization if the argument is unused.
- if (A->user_empty())
- return false;
-
// For now, don't attempt to specialize functions based on the values of
// composite types.
- Type *ArgTy = A->getType() ;
- if (!ArgTy->isSingleValueType())
- return false;
-
- // Specialization of integer and floating point types needs to be explicitly enabled.
- if (!EnableSpecializationForLiteralConstant &&
- (ArgTy->isIntegerTy() || ArgTy->isFloatingPointTy()))
+ if (!A->getType()->isSingleValueType() || A->user_empty())
return false;
- // SCCP solver does not record an argument that will be constructed on
- // stack.
- if (A->hasByValAttr() && !A->getParent()->onlyReadsMemory())
- return false;
-
- // Check the lattice value and decide if we should attemt to specialize,
- // based on this argument. No point in specialization, if the lattice value
- // is already a constant.
- const ValueLatticeElement &LV = Solver.getLatticeValueFor(A);
- if (LV.isUnknownOrUndef() || LV.isConstant() ||
- (LV.isConstantRange() && LV.getConstantRange().isSingleElement())) {
+ // If the argument isn't overdefined, there's nothing to do. It should
+ // already be constant.
+ if (!Solver.getLatticeValueFor(A).isOverdefined()) {
LLVM_DEBUG(dbgs() << "FnSpecialization: Nothing to do, argument "
- << A->getNameOrAsOperand() << " is already constant\n");
+ << A->getNameOrAsOperand()
+ << " is already constant?\n");
return false;
}
SmallVectorImpl<CallArgBinding> &Constants) {
Function *F = A->getParent();
+ // SCCP solver does not record an argument that will be constructed on
+ // stack.
+ if (A->hasByValAttr() && !F->onlyReadsMemory())
+ return;
+
// Iterate over all the call sites of the argument's parent function.
for (User *U : F->users()) {
if (!isa<CallInst>(U) && !isa<InvokeInst>(U))
continue;
}
- // Select for possible specialisation arguments which are constants or
- // are deduced to be constants or constant ranges with a single element.
- Constant *C = dyn_cast<Constant>(V);
- if (!C) {
- const ValueLatticeElement &LV = Solver.getLatticeValueFor(V);
- if (LV.isConstant())
- C = LV.getConstant();
- else if (LV.isConstantRange() &&
- LV.getConstantRange().isSingleElement()) {
- assert(V->getType()->isIntegerTy() && "Non-integral constant range");
- C = Constant::getIntegerValue(
- V->getType(), *LV.getConstantRange().getSingleElement());
- } else
- continue;
- }
-
- Constants.push_back({&CS, C});
+ if (isa<Constant>(V) && (Solver.getLatticeValueFor(V).isConstant() ||
+ EnableSpecializationForLiteralConstant))
+ Constants.push_back({&CS, cast<Constant>(V)});
}
}
+++ /dev/null
-; RUN: opt -S --passes=function-specialization \
-; RUN: -force-function-specialization < %s | FileCheck %s -check-prefix CHECK-NOLIT
-; RUN: opt -S --passes=function-specialization \
-; RUN: -function-specialization-for-literal-constant \
-; RUN: -force-function-specialization < %s | FileCheck %s -check-prefix CHECK-LIT
-
-define dso_local i32 @f0(i32 noundef %x) {
-entry:
- %call = tail call fastcc i32 @neg(i32 noundef %x, i1 noundef zeroext false)
- ret i32 %call
-}
-
-define internal fastcc i32 @neg(i32 noundef %x, i1 noundef zeroext %b) {
-entry:
- %sub = sub nsw i32 0, %x
- %cond = select i1 %b, i32 %sub, i32 %x
- ret i32 %cond
-}
-
-define dso_local i32 @f1(i32 noundef %x) {
-entry:
- %call = tail call fastcc i32 @neg(i32 noundef %x, i1 noundef zeroext true)
- ret i32 %call
-}
-
-define dso_local i32 @g0(i32 noundef %x) {
-entry:
- %call = tail call fastcc i32 @add(i32 noundef %x, i32 noundef 1)
- ret i32 %call
-}
-
-define internal fastcc i32 @add(i32 noundef %x, i32 noundef %y) {
-entry:
- %add = add nsw i32 %y, %x
- ret i32 %add
-}
-
-define dso_local i32 @g1(i32 noundef %x) {
-entry:
- %call = tail call fastcc i32 @add(i32 noundef %x, i32 noundef 2)
- ret i32 %call
-}
-
-define dso_local float @h0(float noundef %x) {
-entry:
- %call = tail call fastcc float @addf(float noundef %x, float noundef 1.000000e+00)
- ret float %call
-}
-
-define internal fastcc float @addf(float noundef %x, float noundef %y) {
-entry:
- %add = fadd float %x, %y
- ret float %add
-}
-
-define dso_local float @h1(float noundef %x) {
-entry:
- %call = tail call fastcc float @addf(float noundef %x, float noundef 2.000000e+00)
- ret float %call
-}
-
-; Check no functions were specialised.
-; CHECK-NOLIT-NOT: @neg.
-; CHECK-NOLIT-NOT: @add.
-; CHECK-NOLIT-NOT: @addf.
-
-; Check all of `neg`, `add`, and `addf` were specialised.
-; CHECK-LIT-DAG: @neg.1
-; CHECK-LIT-DAG: @neg.2
-; CHECK-LIT-DAG: @add.3
-; CHECK-LIT-DAG: @add.4
-; CHECK-LIT-DAG: @addf.5
-; CHECK-LIT-DAG: @addf.6