Skip to content

Commit 5f30b1a

Browse files
authored
[FuncSpec] Improve handling of BinaryOperator instructions (#114534)
When visiting BinaryOperator instructions during estimation of codesize savings for a candidate specialization, don't bail when the other operand is not found to be constant. This allows us to find more constants than we otherwise would, for example `and(false, x)`.
1 parent 5ed3f46 commit 5f30b1a

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

llvm/lib/Transforms/IPO/FunctionSpecialization.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -501,16 +501,17 @@ Constant *InstCostVisitor::visitUnaryOperator(UnaryOperator &I) {
501501
Constant *InstCostVisitor::visitBinaryOperator(BinaryOperator &I) {
502502
assert(LastVisited != KnownConstants.end() && "Invalid iterator!");
503503

504-
bool Swap = I.getOperand(1) == LastVisited->first;
505-
Value *V = Swap ? I.getOperand(0) : I.getOperand(1);
504+
bool ConstOnRHS = I.getOperand(1) == LastVisited->first;
505+
Value *V = ConstOnRHS ? I.getOperand(0) : I.getOperand(1);
506506
Constant *Other = findConstantFor(V, KnownConstants);
507-
if (!Other)
508-
return nullptr;
507+
Value *OtherVal = Other ? Other : V;
508+
Value *ConstVal = LastVisited->second;
509509

510-
Constant *Const = LastVisited->second;
511-
return dyn_cast_or_null<Constant>(Swap ?
512-
simplifyBinOp(I.getOpcode(), Other, Const, SimplifyQuery(DL))
513-
: simplifyBinOp(I.getOpcode(), Const, Other, SimplifyQuery(DL)));
510+
if (ConstOnRHS)
511+
std::swap(ConstVal, OtherVal);
512+
513+
return dyn_cast_or_null<Constant>(
514+
simplifyBinOp(I.getOpcode(), ConstVal, OtherVal, SimplifyQuery(DL)));
514515
}
515516

516517
Constant *FunctionSpecializer::getPromotableAlloca(AllocaInst *Alloca,

llvm/unittests/Transforms/IPO/FunctionSpecializationTest.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,3 +469,38 @@ TEST_F(FunctionSpecializationTest, PhiNode) {
469469
EXPECT_TRUE(Test > 0);
470470
}
471471

472+
TEST_F(FunctionSpecializationTest, BinOp) {
473+
// Verify that we can handle binary operators even when only one operand is
474+
// constant.
475+
const char *ModuleString = R"(
476+
define i32 @foo(i1 %a, i1 %b) {
477+
%and1 = and i1 %a, %b
478+
%and2 = and i1 %b, %and1
479+
%sel = select i1 %and2, i32 1, i32 0
480+
ret i32 %sel
481+
}
482+
)";
483+
484+
Module &M = parseModule(ModuleString);
485+
Function *F = M.getFunction("foo");
486+
FunctionSpecializer Specializer = getSpecializerFor(F);
487+
InstCostVisitor Visitor = Specializer.getInstCostVisitorFor(F);
488+
489+
Constant *False = ConstantInt::getFalse(M.getContext());
490+
BasicBlock &BB = F->front();
491+
Instruction &And1 = BB.front();
492+
Instruction &And2 = *++BB.begin();
493+
Instruction &Select = *++BB.begin();
494+
495+
Cost RefCodeSize = getCodeSizeSavings(And1) + getCodeSizeSavings(And2) +
496+
getCodeSizeSavings(Select);
497+
Cost RefLatency = getLatencySavings(F);
498+
499+
Cost TestCodeSize = Visitor.getCodeSizeSavingsForArg(F->getArg(0), False);
500+
Cost TestLatency = Visitor.getLatencySavingsForKnownConstants();
501+
502+
EXPECT_EQ(TestCodeSize, RefCodeSize);
503+
EXPECT_TRUE(TestCodeSize > 0);
504+
EXPECT_EQ(TestLatency, RefLatency);
505+
EXPECT_TRUE(TestLatency > 0);
506+
}

0 commit comments

Comments
 (0)