Skip to content

Commit 0b13d0d

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 0b13d0d

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

llvm/lib/Target/EVM/EVMCodegenPrepare.cpp

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

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

0 commit comments

Comments
 (0)