Skip to content

Commit d86b664

Browse files
[EVM] Transform icmp ult (add x, CAdd), CCmp -> icmp eq (evm.signextend(b, x)), x
Signed-off-by: Vladimir Radosavljevic <[email protected]>
1 parent da21be1 commit d86b664

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

llvm/lib/Target/EVM/EVMCodegenPrepare.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,50 @@ static bool optimizeAShrInst(Instruction *I) {
136136
return false;
137137
}
138138

139+
static bool optimizeICmp(ICmpInst *I) {
140+
auto *Ty = I->getOperand(0)->getType();
141+
if (!Ty->isIntegerTy(256))
142+
return false;
143+
144+
if (I->getPredicate() == CmpInst::ICMP_ULT) {
145+
Value *X = nullptr;
146+
const APInt *CAdd = nullptr, *CCmp = nullptr;
147+
148+
// icmp ult (add x, CAdd), CCmp -> icmp eq (evm.signextend(b, x)), x
149+
// where CCmp is a power of 2 and CAdd is twice smaller than CCmp.
150+
if (match(I->getOperand(0), m_OneUse(m_c_Add(m_Value(X), m_APInt(CAdd)))) &&
151+
match(I->getOperand(1), m_APInt(CCmp)) && CCmp->isPowerOf2() &&
152+
*CAdd == CCmp->lshr(1)) {
153+
unsigned CCmpLog2 = CCmp->logBase2();
154+
155+
// If CCmpLog2 is not divisible by 8, cannot use signextend.
156+
if (CCmpLog2 % 8 != 0)
157+
return false;
158+
159+
IRBuilder<> Builder(I);
160+
unsigned ByteIdx = (CCmpLog2 / 8) - 1;
161+
162+
// ByteIdx should be in [0, 31].
163+
if (ByteIdx > 31)
164+
return false;
165+
166+
auto *B = ConstantInt::get(Ty, ByteIdx);
167+
auto *SignExtend =
168+
Builder.CreateIntrinsic(Ty, Intrinsic::evm_signextend, {B, X});
169+
auto *NewCmp = Builder.CreateICmp(CmpInst::ICMP_EQ, SignExtend, X);
170+
NewCmp->takeName(I);
171+
I->replaceAllUsesWith(NewCmp);
172+
173+
// Remove add after icmp. If to do otherwise, assert will be triggered.
174+
auto *ToRemove = cast<Instruction>(I->getOperand(0));
175+
I->eraseFromParent();
176+
ToRemove->eraseFromParent();
177+
return true;
178+
}
179+
}
180+
return false;
181+
}
182+
139183
bool EVMCodegenPrepare::runOnFunction(Function &F) {
140184
bool Changed = false;
141185
for (auto &BB : F) {
@@ -146,6 +190,8 @@ bool EVMCodegenPrepare::runOnFunction(Function &F) {
146190
}
147191
if (I.getOpcode() == Instruction::AShr)
148192
Changed |= optimizeAShrInst(&I);
193+
else if (I.getOpcode() == Instruction::ICmp)
194+
Changed |= optimizeICmp(cast<ICmpInst>(&I));
149195
}
150196
}
151197

0 commit comments

Comments
 (0)