[llvm-dev] optimisation issue in an llvm IR pass
Marc via llvm-dev
llvm-dev at lists.llvm.org
Wed Jul 3 09:40:30 PDT 2019
Hi Craig,
On 03.07.19 17:33, Craig Topper wrote:
> Don't the CreateICmp calls return a Value* with an i1 type? But then
> they are added to an i8 type? Not sure that works.
I had that initially:
auto cf = IRB.CreateICmpULT(Incr, ConstantInt::get(Int8Ty, 1));
auto carry = IRB.CreateZExt(cf, Int8Ty);
Incr = IRB.CreateAdd(Incr, carry);
it makes no difference to the generated assembly
> Have you tried using the llvm.uadd.with.overflow.i8 intrinsic?
we have tried this:
CallInst *AddOv =
IRB.CreateBinaryIntrinsic(Intrinsic::uadd_with_overflow, Counter,
ConstantInt::get(Int8Ty, 1));
AddOv->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
Value *SumWithOverflowBit = AddOv;
Incr = IRB.CreateAdd(IRB.CreateExtractValue(SumWithOverflowBit, 0),
IRB.CreateZExt(IRB.CreateExtractValue(SumWithOverflowBit, 1), Int8Ty));
but that generated exactly the same as
auto cf = IRB.CreateICmpULT(Incr, ConstantInt::get(Int8Ty, 1));
Incr = IRB.CreateAdd(Incr, cf);
All the above create (with llvm 6.0, 7 and 8):
mov dl,BYTE PTR [rsi+rdi*1]
mov ecx,edx // <- not needed
add cl,0x1 // <- should be done to dl instead
adc dl,0x1
mov BYTE PTR [rsi+rdi*1],dl
Thanks!
Regards,
Marc
>
> ~Craig
>
>
> On Wed, Jul 3, 2019 at 4:01 AM Marc via llvm-dev
> <llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>> wrote:
>
> Hello,
>
> I have an optimisation issue in an llvm IR pass - the issue being that
> unnecessary instructions are generated in the final assembly (with -O3).
>
> I want to create the following assembly snippet:
>
> mov dl,BYTE PTR [rsi+rdi*1]
> add dl,0x1
> adc dl,0x0
> mov BYTE PTR [rsi+rdi*1],dl
>
> however what is created is (variant #1):
>
> mov dl,BYTE PTR [rsi+rdx*1]
> add dl,0x1
> cmp dl,0x1 // <- not needed
> adc dl,0x0
> mov BYTE PTR [rsi+rdi*1],dl
>
> in variant #2 the following is created:
>
> mov dl,BYTE PTR [rsi+rdi*1]
> mov ecx,edx // <- not needed
> add cl,0x1 // <- should be done to dl instead
> adc dl,0x1
> mov BYTE PTR [rsi+rdi*1],dl
>
> Far below are both variants with the full code around it, however the
> difference in both variants is this:
>
> //variant1
> auto cf = IRB.CreateICmpEQ(Incr, ConstantInt::get(Int8Ty, 0));
> Incr = IRB.CreateAdd(Incr, cf);
>
> //variant2
> auto cf = IRB.CreateICmpULT(Incr, ConstantInt::get(Int8Ty, 1));
> Incr = IRB.CreateAdd(Incr, cf);
>
> //interestingly this totally different approach creates the same
> instructions as variant2
> CallInst *AddOv = IRB.CreateBinaryIntrinsic(Intrinsic::uadd_with_over
> flow, Counter, ConstantInt::get(Int8Ty, 1));
> AddOv->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
> Value *SumWithOverflowBit = AddOv;
> Incr = IRB.CreateAdd(IRB.CreateExtractValue(SumWithOverflowBit, 0),
> IRB.CreateZExt(IRB.CreateExtractValue(SumWithOverflowBit, 1), Int8Ty));
>
> So - How do I have to write the code that the target code has a chance
> of being generated?
> For me its the same result on LLVM 6.0 and 7.
>
> Alternatively
> add BYTE PTR [rsi+rdi*1],0x1
> adc BYTE PTR [rsi+rdi*1],0x0
> would work as well.
>
> Thank you very much!
>
> Regards,
> Marc
>
> -> Below now is the full llvm IR pass code
>
> // vvv same code before both variants
> LoadInst *PrevLoc = IRB.CreateLoad(AFLPrevLoc);
> PrevLoc->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
> Value *PrevLocCasted = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty());
>
> LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
> MapPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
> Value *MapPtrIdx = IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocCasted,
> CurLoc));
>
> LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
> Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
>
> Value *Incr = IRB.CreateAdd(Counter, ConstantInt::get(Int8Ty, 1));
> // ^^^ same code before both variants
>
> // CODE FOR VARIANT #1
> auto cf = IRB.CreateICmpEQ(Incr, ConstantInt::get(Int8Ty, 0));
> Incr = IRB.CreateAdd(Incr, cf);
>
> // CODE FOR VARIANT #2
> auto cf = IRB.CreateICmpULT(Incr, ConstantInt::get(Int8Ty, 1));
> Incr = IRB.CreateAdd(Incr, cf);
>
> // vvv same code after both variants
> IRB.CreateStore(Incr,
> MapPtrIdx)->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C,
> None));
> StoreInst *Store = IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >>
> 1), AFLPrevLoc);
> Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
> // ^^^ same code after both variants
>
>
> --
> Marc Heuse
> www.mh-sec.de <http://www.mh-sec.de>
>
> PGP: AF3D 1D4C D810 F0BB 977D 3807 C7EE D0A0 6BE9 F573
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
--
Marc Heuse
Mobil: +49 177 9611560
Fax: +49 30 37309726
www.mh-sec.de
Marc Heuse - IT-Security Consulting
Winsstr. 68
10405 Berlin
Ust.-Ident.-Nr.: DE244222388
PGP: AF3D 1D4C D810 F0BB 977D 3807 C7EE D0A0 6BE9 F573
More information about the llvm-dev
mailing list