@@ -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+
139184bool 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