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
Craig Topper via llvm-dev
2019-Jul-04 00:28 UTC
[llvm-dev] optimisation issue in an llvm IR pass
This patch fixes the issue. I haven't checked our lit tests yet to see what
effect this has and if we can commit it.
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -2967,7 +2967,8 @@ SDValue DAGCombiner::visitADDCARRYLike(SDValue N0,
SDValue N1, SDValue CarryIn,
// Iff the flag result is dead:
// (addcarry (add|uaddo X, Y), 0, Carry) -> (addcarry X, Y, Carry)
if ((N0.getOpcode() == ISD::ADD ||
- (N0.getOpcode() == ISD::UADDO && N0.getResNo() == 0)) &&
+ (N0.getOpcode() == ISD::UADDO && N0.getResNo() == 0 &&
+ N0.getValue(1) != CarryIn)) &&
isNullConstant(N1) && !N->hasAnyUseOfValue(1))
return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(),
N0.getOperand(0), N0.getOperand(1), CarryIn);
~Craig
On Wed, Jul 3, 2019 at 9:40 AM Marc <mh at mh-sec.de> wrote:
> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20190703/0eeea0d3/attachment.html>
Craig Topper via llvm-dev
2019-Jul-04 01:53 UTC
[llvm-dev] optimisation issue in an llvm IR pass
Patch posted for review here https://reviews.llvm.org/D64190 ~Craig On Wed, Jul 3, 2019 at 5:28 PM Craig Topper <craig.topper at gmail.com> wrote:> This patch fixes the issue. I haven't checked our lit tests yet to see > what effect this has and if we can commit it. > > lib/CodeGen/SelectionDAG/DAGCombiner.cpp > > @@ -2967,7 +2967,8 @@ SDValue DAGCombiner::visitADDCARRYLike(SDValue N0, > SDValue N1, SDValue CarryIn, > > // Iff the flag result is dead: > > // (addcarry (add|uaddo X, Y), 0, Carry) -> (addcarry X, Y, Carry) > > if ((N0.getOpcode() == ISD::ADD || > > - (N0.getOpcode() == ISD::UADDO && N0.getResNo() == 0)) && > > + (N0.getOpcode() == ISD::UADDO && N0.getResNo() == 0 && > > + N0.getValue(1) != CarryIn)) && > > isNullConstant(N1) && !N->hasAnyUseOfValue(1)) > > return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(), > > N0.getOperand(0), N0.getOperand(1), CarryIn); > > ~Craig > > > On Wed, Jul 3, 2019 at 9:40 AM Marc <mh at mh-sec.de> wrote: > >> 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 >> >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190703/8233aff5/attachment-0001.html>
Hello Craig, thanks for filing a patch! I would have hoped that the issue is on my side and not an issue in llvm though ;) Is that patch for llvm 9 (only)? Regards, Marc On 04.07.19 02:28, Craig Topper wrote:> This patch fixes the issue. I haven't checked our lit tests yet to see > what effect this has and if we can commit it. > > lib/CodeGen/SelectionDAG/DAGCombiner.cpp > > @@ -2967,7 +2967,8 @@SDValue DAGCombiner::visitADDCARRYLike(SDValue N0, > SDValue N1, SDValue CarryIn, > > // Iff the flag result is dead: > > // (addcarry (add|uaddo X, Y), 0, Carry) -> (addcarry X, Y, Carry) > > if ((N0.getOpcode() == ISD::ADD || > > - (N0.getOpcode() == ISD::UADDO && N0.getResNo() == 0)) && > > + (N0.getOpcode() == ISD::UADDO && N0.getResNo() == 0 && > > + N0.getValue(1) != CarryIn)) && > > isNullConstant(N1) && !N->hasAnyUseOfValue(1)) > > return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(), > > N0.getOperand(0), N0.getOperand(1), CarryIn); > > > ~Craig > > > On Wed, Jul 3, 2019 at 9:40 AM Marc <mh at mh-sec.de <mailto:mh at mh-sec.de>> > wrote: > > 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> > <mailto: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> <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> > <mailto:llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>> > > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > >