xref: /aosp_15_r20/external/AFLplusplus/instrumentation/split-compares-pass.so.cc (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
1 /*
2  * Copyright 2016 laf-intel
3  * extended for floating point by Heiko Eißfeldt
4  * adapted to new pass manager by Heiko Eißfeldt
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     https://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 
23 #include <list>
24 #include <string>
25 #include <fstream>
26 #include <sys/time.h>
27 
28 #include "llvm/Config/llvm-config.h"
29 
30 #include "llvm/Pass.h"
31 #include "llvm/Support/raw_ostream.h"
32 
33 #if LLVM_MAJOR >= 11
34   #include "llvm/Passes/PassPlugin.h"
35   #include "llvm/Passes/PassBuilder.h"
36   #include "llvm/IR/PassManager.h"
37 #else
38   #include "llvm/IR/LegacyPassManager.h"
39   #include "llvm/Transforms/IPO/PassManagerBuilder.h"
40 #endif
41 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
42 #include "llvm/IR/Module.h"
43 #if LLVM_VERSION_MAJOR >= 14                /* how about stable interfaces? */
44   #include "llvm/Passes/OptimizationLevel.h"
45 #endif
46 
47 #include "llvm/IR/IRBuilder.h"
48 #if LLVM_VERSION_MAJOR >= 4 || \
49     (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
50   #include "llvm/IR/Verifier.h"
51   #include "llvm/IR/DebugInfo.h"
52 #else
53   #include "llvm/Analysis/Verifier.h"
54   #include "llvm/DebugInfo.h"
55   #define nullptr 0
56 #endif
57 
58 using namespace llvm;
59 #include "afl-llvm-common.h"
60 
61 // uncomment this toggle function verification at each step. horribly slow, but
62 // helps to pinpoint a potential problem in the splitting code.
63 // #define VERIFY_TOO_MUCH 1
64 
65 namespace {
66 
67 #if LLVM_MAJOR >= 11
68 class SplitComparesTransform : public PassInfoMixin<SplitComparesTransform> {
69 
70  public:
71   //  static char ID;
SplitComparesTransform()72   SplitComparesTransform() : enableFPSplit(0) {
73 
74 #else
75 class SplitComparesTransform : public ModulePass {
76 
77  public:
78   static char ID;
79   SplitComparesTransform() : ModulePass(ID), enableFPSplit(0) {
80 
81 #endif
82 
83     initInstrumentList();
84 
85   }
86 
87 #if LLVM_MAJOR >= 11
88   PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
89 #else
90   bool runOnModule(Module &M) override;
91 #endif
92 
93  private:
94   int enableFPSplit;
95 
96   unsigned target_bitwidth = 8;
97 
98   size_t count = 0;
99 
100   size_t splitFPCompares(Module &M);
101   bool   simplifyFPCompares(Module &M);
102   size_t nextPowerOfTwo(size_t in);
103 
104   using CmpWorklist = SmallVector<CmpInst *, 8>;
105 
106   /// simplify the comparison and then split the comparison until the
107   /// target_bitwidth is reached.
108   bool simplifyAndSplit(CmpInst *I, Module &M);
109   /// simplify a non-strict comparison (e.g., less than or equals)
110   bool simplifyOrEqualsCompare(CmpInst *IcmpInst, Module &M,
111                                CmpWorklist &worklist);
112   /// simplify a signed comparison (signed less or greater than)
113   bool simplifySignedCompare(CmpInst *IcmpInst, Module &M,
114                              CmpWorklist &worklist);
115   /// splits an icmp into nested icmps recursivly until target_bitwidth is
116   /// reached
117   bool splitCompare(CmpInst *I, Module &M, CmpWorklist &worklist);
118 
119   /// print an error to llvm's errs stream, but only if not ordered to be quiet
120   void reportError(const StringRef msg, Instruction *I, Module &M) {
121 
122     if (!be_quiet) {
123 
124       errs() << "[AFL++ SplitComparesTransform] ERROR: " << msg << "\n";
125       if (debug) {
126 
127         if (I) {
128 
129           errs() << "Instruction = " << *I << "\n";
130           if (auto BB = I->getParent()) {
131 
132             if (auto F = BB->getParent()) {
133 
134               if (F->hasName()) {
135 
136                 errs() << "|-> in function " << F->getName() << " ";
137 
138               }
139 
140             }
141 
142           }
143 
144         }
145 
146         auto n = M.getName();
147         if (n.size() > 0) { errs() << "in module " << n << "\n"; }
148 
149       }
150 
151     }
152 
153   }
154 
155   bool isSupportedBitWidth(unsigned bitw) {
156 
157     // IDK whether the icmp code works on other bitwidths. I guess not? So we
158     // try to avoid dealing with other weird icmp's that llvm might use (looking
159     // at you `icmp i0`).
160     switch (bitw) {
161 
162       case 8:
163       case 16:
164       case 32:
165       case 64:
166       case 128:
167       case 256:
168         return true;
169       default:
170         return false;
171 
172     }
173 
174   }
175 
176 };
177 
178 }  // namespace
179 
180 #if LLVM_MAJOR >= 11
181 extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
llvmGetPassPluginInfo()182 llvmGetPassPluginInfo() {
183 
184   return {LLVM_PLUGIN_API_VERSION, "splitcompares", "v0.1",
185           /* lambda to insert our pass into the pass pipeline. */
186           [](PassBuilder &PB) {
187 
188   #if 1
189     #if LLVM_VERSION_MAJOR <= 13
190             using OptimizationLevel = typename PassBuilder::OptimizationLevel;
191     #endif
192             PB.registerOptimizerLastEPCallback(
193                 [](ModulePassManager &MPM, OptimizationLevel OL) {
194 
195                   MPM.addPass(SplitComparesTransform());
196 
197                 });
198 
199   /* TODO LTO registration */
200   #else
201             using PipelineElement = typename PassBuilder::PipelineElement;
202             PB.registerPipelineParsingCallback([](StringRef          Name,
203                                                   ModulePassManager &MPM,
204                                                   ArrayRef<PipelineElement>) {
205 
206               if (Name == "splitcompares") {
207 
208                 MPM.addPass(SplitComparesTransform());
209                 return true;
210 
211               } else {
212 
213                 return false;
214 
215               }
216 
217             });
218 
219   #endif
220 
221           }};
222 
223 }
224 
225 #else
226 char SplitComparesTransform::ID = 0;
227 #endif
228 
229 /// This function splits FCMP instructions with xGE or xLE predicates into two
230 /// FCMP instructions with predicate xGT or xLT and EQ
simplifyFPCompares(Module & M)231 bool SplitComparesTransform::simplifyFPCompares(Module &M) {
232 
233   LLVMContext               &C = M.getContext();
234   std::vector<Instruction *> fcomps;
235   IntegerType               *Int1Ty = IntegerType::getInt1Ty(C);
236 
237   /* iterate over all functions, bbs and instruction and add
238    * all integer comparisons with >= and <= predicates to the icomps vector */
239   for (auto &F : M) {
240 
241     if (!isInInstrumentList(&F, MNAME)) continue;
242 
243     for (auto &BB : F) {
244 
245       for (auto &IN : BB) {
246 
247         CmpInst *selectcmpInst = nullptr;
248 
249         if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) {
250 
251           if (enableFPSplit &&
252               (selectcmpInst->getPredicate() == CmpInst::FCMP_OGE ||
253                selectcmpInst->getPredicate() == CmpInst::FCMP_UGE ||
254                selectcmpInst->getPredicate() == CmpInst::FCMP_OLE ||
255                selectcmpInst->getPredicate() == CmpInst::FCMP_ULE)) {
256 
257             auto op0 = selectcmpInst->getOperand(0);
258             auto op1 = selectcmpInst->getOperand(1);
259 
260             Type *TyOp0 = op0->getType();
261             Type *TyOp1 = op1->getType();
262 
263             /* this is probably not needed but we do it anyway */
264             if (TyOp0 != TyOp1) { continue; }
265 
266             if (TyOp0->isArrayTy() || TyOp0->isVectorTy()) { continue; }
267 
268             fcomps.push_back(selectcmpInst);
269 
270           }
271 
272         }
273 
274       }
275 
276     }
277 
278   }
279 
280   if (!fcomps.size()) { return false; }
281 
282   /* transform for floating point */
283   for (auto &FcmpInst : fcomps) {
284 
285     BasicBlock *bb = FcmpInst->getParent();
286 
287     auto op0 = FcmpInst->getOperand(0);
288     auto op1 = FcmpInst->getOperand(1);
289 
290     /* find out what the new predicate is going to be */
291     auto cmp_inst = dyn_cast<CmpInst>(FcmpInst);
292     if (!cmp_inst) { continue; }
293     auto               pred = cmp_inst->getPredicate();
294     CmpInst::Predicate new_pred;
295 
296     switch (pred) {
297 
298       case CmpInst::FCMP_UGE:
299         new_pred = CmpInst::FCMP_UGT;
300         break;
301       case CmpInst::FCMP_OGE:
302         new_pred = CmpInst::FCMP_OGT;
303         break;
304       case CmpInst::FCMP_ULE:
305         new_pred = CmpInst::FCMP_ULT;
306         break;
307       case CmpInst::FCMP_OLE:
308         new_pred = CmpInst::FCMP_OLT;
309         break;
310       default:  // keep the compiler happy
311         continue;
312 
313     }
314 
315     /* split before the fcmp instruction */
316     BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(FcmpInst));
317 
318     /* the old bb now contains a unconditional jump to the new one (end_bb)
319      * we need to delete it later */
320 
321     /* create the FCMP instruction with new_pred and add it to the old basic
322      * block bb it is now at the position where the old FcmpInst was */
323     Instruction *fcmp_np;
324     fcmp_np = CmpInst::Create(Instruction::FCmp, new_pred, op0, op1);
325 #if LLVM_MAJOR >= 16
326     fcmp_np->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
327 #else
328     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
329                              fcmp_np);
330 #endif
331 
332     /* create a new basic block which holds the new EQ fcmp */
333     Instruction *fcmp_eq;
334     /* insert middle_bb before end_bb */
335     BasicBlock *middle_bb =
336         BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
337     fcmp_eq = CmpInst::Create(Instruction::FCmp, CmpInst::FCMP_OEQ, op0, op1);
338 #if LLVM_MAJOR >= 16
339     fcmp_eq->insertInto(middle_bb, middle_bb->end());
340 #else
341     middle_bb->getInstList().push_back(fcmp_eq);
342 #endif
343     /* add an unconditional branch to the end of middle_bb with destination
344      * end_bb */
345     BranchInst::Create(end_bb, middle_bb);
346 
347     /* replace the uncond branch with a conditional one, which depends on the
348      * new_pred fcmp. True goes to end, false to the middle (injected) bb */
349     auto term = bb->getTerminator();
350     BranchInst::Create(end_bb, middle_bb, fcmp_np, bb);
351     term->eraseFromParent();
352 
353     /* replace the old FcmpInst (which is the first inst in end_bb) with a PHI
354      * inst to wire up the loose ends */
355     PHINode *PN = PHINode::Create(Int1Ty, 2, "");
356     /* the first result depends on the outcome of fcmp_eq */
357     PN->addIncoming(fcmp_eq, middle_bb);
358     /* if the source was the original bb we know that the fcmp_np yielded true
359      * hence we can hardcode this value */
360     PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb);
361     /* replace the old FcmpInst with our new and shiny PHI inst */
362     BasicBlock::iterator ii(FcmpInst);
363 #if LLVM_MAJOR >= 16
364     ReplaceInstWithInst(FcmpInst->getParent(), ii, PN);
365 #else
366     ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
367 #endif
368 
369   }
370 
371   return true;
372 
373 }
374 
375 /// This function splits ICMP instructions with xGE or xLE predicates into two
376 /// ICMP instructions with predicate xGT or xLT and EQ
simplifyOrEqualsCompare(CmpInst * IcmpInst,Module & M,CmpWorklist & worklist)377 bool SplitComparesTransform::simplifyOrEqualsCompare(CmpInst     *IcmpInst,
378                                                      Module      &M,
379                                                      CmpWorklist &worklist) {
380 
381   LLVMContext &C = M.getContext();
382   IntegerType *Int1Ty = IntegerType::getInt1Ty(C);
383 
384   /* find out what the new predicate is going to be */
385   auto cmp_inst = dyn_cast<CmpInst>(IcmpInst);
386   if (!cmp_inst) { return false; }
387 
388   BasicBlock *bb = IcmpInst->getParent();
389 
390   auto op0 = IcmpInst->getOperand(0);
391   auto op1 = IcmpInst->getOperand(1);
392 
393   CmpInst::Predicate pred = cmp_inst->getPredicate();
394   CmpInst::Predicate new_pred;
395 
396   switch (pred) {
397 
398     case CmpInst::ICMP_UGE:
399       new_pred = CmpInst::ICMP_UGT;
400       break;
401     case CmpInst::ICMP_SGE:
402       new_pred = CmpInst::ICMP_SGT;
403       break;
404     case CmpInst::ICMP_ULE:
405       new_pred = CmpInst::ICMP_ULT;
406       break;
407     case CmpInst::ICMP_SLE:
408       new_pred = CmpInst::ICMP_SLT;
409       break;
410     default:  // keep the compiler happy
411       return false;
412 
413   }
414 
415   /* split before the icmp instruction */
416   BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(IcmpInst));
417 
418   /* the old bb now contains a unconditional jump to the new one (end_bb)
419    * we need to delete it later */
420 
421   /* create the ICMP instruction with new_pred and add it to the old basic
422    * block bb it is now at the position where the old IcmpInst was */
423   CmpInst *icmp_np = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1);
424 #if LLVM_MAJOR >= 16
425   icmp_np->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
426 #else
427   bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), icmp_np);
428 #endif
429 
430   /* create a new basic block which holds the new EQ icmp */
431   CmpInst *icmp_eq;
432   /* insert middle_bb before end_bb */
433   BasicBlock *middle_bb =
434       BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
435   icmp_eq = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, op0, op1);
436 #if LLVM_MAJOR >= 16
437   icmp_eq->insertInto(middle_bb, middle_bb->end());
438 #else
439   middle_bb->getInstList().push_back(icmp_eq);
440 #endif
441   /* add an unconditional branch to the end of middle_bb with destination
442    * end_bb */
443   BranchInst::Create(end_bb, middle_bb);
444 
445   /* replace the uncond branch with a conditional one, which depends on the
446    * new_pred icmp. True goes to end, false to the middle (injected) bb */
447   auto term = bb->getTerminator();
448   BranchInst::Create(end_bb, middle_bb, icmp_np, bb);
449   term->eraseFromParent();
450 
451   /* replace the old IcmpInst (which is the first inst in end_bb) with a PHI
452    * inst to wire up the loose ends */
453   PHINode *PN = PHINode::Create(Int1Ty, 2, "");
454   /* the first result depends on the outcome of icmp_eq */
455   PN->addIncoming(icmp_eq, middle_bb);
456   /* if the source was the original bb we know that the icmp_np yielded true
457    * hence we can hardcode this value */
458   PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb);
459   /* replace the old IcmpInst with our new and shiny PHI inst */
460   BasicBlock::iterator ii(IcmpInst);
461 #if LLVM_MAJOR >= 16
462   ReplaceInstWithInst(IcmpInst->getParent(), ii, PN);
463 #else
464   ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN);
465 #endif
466   if (new_pred == CmpInst::ICMP_SGT || new_pred == CmpInst::ICMP_SLT) {
467 
468     simplifySignedCompare(icmp_np, M, worklist);
469 
470   }
471 
472   worklist.push_back(icmp_eq);
473 
474   return true;
475 
476 }
477 
478 /// Simplify a signed comparison operator by splitting it into a unsigned and
479 /// bit comparison. add all resulting comparisons to
480 /// the worklist passed as a reference.
simplifySignedCompare(CmpInst * IcmpInst,Module & M,CmpWorklist & worklist)481 bool SplitComparesTransform::simplifySignedCompare(CmpInst *IcmpInst, Module &M,
482                                                    CmpWorklist &worklist) {
483 
484   LLVMContext &C = M.getContext();
485   IntegerType *Int1Ty = IntegerType::getInt1Ty(C);
486 
487   BasicBlock *bb = IcmpInst->getParent();
488 
489   auto op0 = IcmpInst->getOperand(0);
490   auto op1 = IcmpInst->getOperand(1);
491 
492   IntegerType *intTyOp0 = dyn_cast<IntegerType>(op0->getType());
493   if (!intTyOp0) { return false; }
494   unsigned     bitw = intTyOp0->getBitWidth();
495   IntegerType *IntType = IntegerType::get(C, bitw);
496 
497   /* get the new predicate */
498   auto cmp_inst = dyn_cast<CmpInst>(IcmpInst);
499   if (!cmp_inst) { return false; }
500   auto               pred = cmp_inst->getPredicate();
501   CmpInst::Predicate new_pred;
502 
503   if (pred == CmpInst::ICMP_SGT) {
504 
505     new_pred = CmpInst::ICMP_UGT;
506 
507   } else {
508 
509     new_pred = CmpInst::ICMP_ULT;
510 
511   }
512 
513   BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(IcmpInst));
514 
515   /* create a 1 bit compare for the sign bit. to do this shift and trunc
516    * the original operands so only the first bit remains.*/
517   Value *s_op0, *t_op0, *s_op1, *t_op1, *icmp_sign_bit;
518 
519   IRBuilder<> IRB(bb->getTerminator());
520   s_op0 = IRB.CreateLShr(op0, ConstantInt::get(IntType, bitw - 1));
521   t_op0 = IRB.CreateTruncOrBitCast(s_op0, Int1Ty);
522   s_op1 = IRB.CreateLShr(op1, ConstantInt::get(IntType, bitw - 1));
523   t_op1 = IRB.CreateTruncOrBitCast(s_op1, Int1Ty);
524   /* compare of the sign bits */
525   icmp_sign_bit = IRB.CreateICmp(CmpInst::ICMP_EQ, t_op0, t_op1);
526 
527   /* create a new basic block which is executed if the signedness bit is
528    * different */
529   CmpInst    *icmp_inv_sig_cmp;
530   BasicBlock *sign_bb =
531       BasicBlock::Create(C, "sign", end_bb->getParent(), end_bb);
532   if (pred == CmpInst::ICMP_SGT) {
533 
534     /* if we check for > and the op0 positive and op1 negative then the final
535      * result is true. if op0 negative and op1 pos, the cmp must result
536      * in false
537      */
538     icmp_inv_sig_cmp =
539         CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_op0, t_op1);
540 
541   } else {
542 
543     /* just the inverse of the above statement */
544     icmp_inv_sig_cmp =
545         CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_op0, t_op1);
546 
547   }
548 
549 #if LLVM_MAJOR >= 16
550   icmp_inv_sig_cmp->insertInto(sign_bb, sign_bb->end());
551 #else
552   sign_bb->getInstList().push_back(icmp_inv_sig_cmp);
553 #endif
554   BranchInst::Create(end_bb, sign_bb);
555 
556   /* create a new bb which is executed if signedness is equal */
557   CmpInst    *icmp_usign_cmp;
558   BasicBlock *middle_bb =
559       BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
560   /* we can do a normal unsigned compare now */
561   icmp_usign_cmp = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1);
562 
563 #if LLVM_MAJOR >= 16
564   icmp_usign_cmp->insertInto(middle_bb, middle_bb->end());
565 #else
566   middle_bb->getInstList().push_back(icmp_usign_cmp);
567 #endif
568   BranchInst::Create(end_bb, middle_bb);
569 
570   auto term = bb->getTerminator();
571   /* if the sign is eq do a normal unsigned cmp, else we have to check the
572    * signedness bit */
573   BranchInst::Create(middle_bb, sign_bb, icmp_sign_bit, bb);
574   term->eraseFromParent();
575 
576   PHINode *PN = PHINode::Create(Int1Ty, 2, "");
577 
578   PN->addIncoming(icmp_usign_cmp, middle_bb);
579   PN->addIncoming(icmp_inv_sig_cmp, sign_bb);
580 
581   BasicBlock::iterator ii(IcmpInst);
582 #if LLVM_MAJOR >= 16
583   ReplaceInstWithInst(IcmpInst->getParent(), ii, PN);
584 #else
585   ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN);
586 #endif
587 
588   // save for later
589   worklist.push_back(icmp_usign_cmp);
590 
591   // signed comparisons are not supported by the splitting code, so we must not
592   // add it to the worklist.
593   // worklist.push_back(icmp_inv_sig_cmp);
594 
595   return true;
596 
597 }
598 
splitCompare(CmpInst * cmp_inst,Module & M,CmpWorklist & worklist)599 bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M,
600                                           CmpWorklist &worklist) {
601 
602   auto pred = cmp_inst->getPredicate();
603   switch (pred) {
604 
605     case CmpInst::ICMP_EQ:
606     case CmpInst::ICMP_NE:
607     case CmpInst::ICMP_UGT:
608     case CmpInst::ICMP_ULT:
609     case CmpInst::ICMP_UGE:
610     case CmpInst::ICMP_ULE:
611     case CmpInst::ICMP_SGT:
612     case CmpInst::ICMP_SLT:
613     case CmpInst::ICMP_SGE:
614     case CmpInst::ICMP_SLE:
615       break;
616     default:
617       if (!be_quiet)
618         fprintf(stderr, "Error: split-compare: Unsupported predicate (%u)\n",
619                 pred);
620       // unsupported predicate!
621       return false;
622 
623   }
624 
625   auto op0 = cmp_inst->getOperand(0);
626   auto op1 = cmp_inst->getOperand(1);
627 
628   // get bitwidth by checking the bitwidth of the first operator
629   IntegerType *intTyOp0 = dyn_cast<IntegerType>(op0->getType());
630   if (!intTyOp0) {
631 
632     // not an integer type
633     if (!be_quiet)
634       fprintf(stderr, "Error: split-compare: not an integer type\n");
635     return false;
636 
637   }
638 
639   unsigned bitw = intTyOp0->getBitWidth();
640   if (bitw == target_bitwidth) {
641 
642     // already the target bitwidth so we have to do nothing here.
643     return true;
644 
645   }
646 
647   LLVMContext &C = M.getContext();
648   IntegerType *Int1Ty = IntegerType::getInt1Ty(C);
649   BasicBlock  *bb = cmp_inst->getParent();
650   IntegerType *OldIntType = IntegerType::get(C, bitw);
651   IntegerType *NewIntType = IntegerType::get(C, bitw / 2);
652   BasicBlock  *end_bb = bb->splitBasicBlock(BasicBlock::iterator(cmp_inst));
653   CmpInst     *icmp_high, *icmp_low;
654 
655   /* create the comparison of the top halves of the original operands */
656   Value *s_op0, *op0_high, *s_op1, *op1_high;
657 
658   IRBuilder<> IRB(bb->getTerminator());
659 
660   s_op0 = IRB.CreateBinOp(Instruction::LShr, op0,
661                           ConstantInt::get(OldIntType, bitw / 2));
662   op0_high = IRB.CreateTruncOrBitCast(s_op0, NewIntType);
663 
664   s_op1 = IRB.CreateBinOp(Instruction::LShr, op1,
665                           ConstantInt::get(OldIntType, bitw / 2));
666   op1_high = IRB.CreateTruncOrBitCast(s_op1, NewIntType);
667   icmp_high = cast<CmpInst>(IRB.CreateICmp(pred, op0_high, op1_high));
668 
669   PHINode *PN = nullptr;
670 
671   /* now we have to destinguish between == != and > < */
672   switch (pred) {
673 
674     case CmpInst::ICMP_EQ:
675     case CmpInst::ICMP_NE: {
676 
677       /* transformation for == and != icmps */
678 
679       /* create a compare for the lower half of the original operands */
680       BasicBlock *cmp_low_bb =
681           BasicBlock::Create(C, "" /*"injected"*/, end_bb->getParent(), end_bb);
682 
683       Value      *op0_low, *op1_low;
684       IRBuilder<> Builder(cmp_low_bb);
685 
686       op0_low = Builder.CreateTrunc(op0, NewIntType);
687       op1_low = Builder.CreateTrunc(op1, NewIntType);
688       icmp_low = cast<CmpInst>(Builder.CreateICmp(pred, op0_low, op1_low));
689 
690       BranchInst::Create(end_bb, cmp_low_bb);
691 
692       /* dependent on the cmp of the high parts go to the end or go on with
693        * the comparison */
694       auto term = bb->getTerminator();
695 
696       if (pred == CmpInst::ICMP_EQ) {
697 
698         BranchInst::Create(cmp_low_bb, end_bb, icmp_high, bb);
699 
700       } else {
701 
702         // CmpInst::ICMP_NE
703         BranchInst::Create(end_bb, cmp_low_bb, icmp_high, bb);
704 
705       }
706 
707       term->eraseFromParent();
708 
709       /* create the PHI and connect the edges accordingly */
710       PN = PHINode::Create(Int1Ty, 2, "");
711       PN->addIncoming(icmp_low, cmp_low_bb);
712       Value *val = nullptr;
713       if (pred == CmpInst::ICMP_EQ) {
714 
715         val = ConstantInt::get(Int1Ty, 0);
716 
717       } else {
718 
719         /* CmpInst::ICMP_NE */
720         val = ConstantInt::get(Int1Ty, 1);
721 
722       }
723 
724       PN->addIncoming(val, icmp_high->getParent());
725       break;
726 
727     }
728 
729     case CmpInst::ICMP_SGE:
730     case CmpInst::ICMP_SLE:
731     case CmpInst::ICMP_SGT:
732     case CmpInst::ICMP_SLT:
733     case CmpInst::ICMP_UGE:
734     case CmpInst::ICMP_ULE:
735     case CmpInst::ICMP_UGT:
736     case CmpInst::ICMP_ULT: {
737 
738       /* transformations for < and > */
739 
740       /* create a basic block which checks for the inverse predicate.
741        * if this is true we can go to the end if not we have to go to the
742        * bb which checks the lower half of the operands */
743       Instruction *op0_low, *op1_low;
744       CmpInst     *icmp_inv_cmp = nullptr;
745       BasicBlock  *inv_cmp_bb =
746           BasicBlock::Create(C, "inv_cmp", end_bb->getParent(), end_bb);
747       if (pred == CmpInst::ICMP_UGT) {
748 
749         icmp_inv_cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT,
750                                        op0_high, op1_high);
751 
752       } else if (pred == CmpInst::ICMP_ULT) {
753 
754         icmp_inv_cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT,
755                                        op0_high, op1_high);
756 
757       } else {
758 
759         // Never gonna appen
760         if (!be_quiet)
761           fprintf(stderr,
762                   "Error: split-compare: Equals or signed not removed: %d\n",
763                   pred);
764 
765       }
766 
767 #if LLVM_MAJOR >= 16
768       icmp_inv_cmp->insertInto(inv_cmp_bb, inv_cmp_bb->end());
769 #else
770       inv_cmp_bb->getInstList().push_back(icmp_inv_cmp);
771 #endif
772       worklist.push_back(icmp_inv_cmp);
773 
774       auto term = bb->getTerminator();
775       term->eraseFromParent();
776       BranchInst::Create(end_bb, inv_cmp_bb, icmp_high, bb);
777 
778       /* create a bb which handles the cmp of the lower halves */
779       BasicBlock *cmp_low_bb =
780           BasicBlock::Create(C, "" /*"injected"*/, end_bb->getParent(), end_bb);
781       op0_low = new TruncInst(op0, NewIntType);
782       op1_low = new TruncInst(op1, NewIntType);
783       icmp_low = CmpInst::Create(Instruction::ICmp, pred, op0_low, op1_low);
784 
785 #if LLVM_MAJOR >= 16
786       op0_low->insertInto(cmp_low_bb, cmp_low_bb->end());
787       op1_low->insertInto(cmp_low_bb, cmp_low_bb->end());
788       icmp_low->insertInto(cmp_low_bb, cmp_low_bb->end());
789 #else
790       cmp_low_bb->getInstList().push_back(op0_low);
791       cmp_low_bb->getInstList().push_back(op1_low);
792       cmp_low_bb->getInstList().push_back(icmp_low);
793 #endif
794       BranchInst::Create(end_bb, cmp_low_bb);
795 
796       BranchInst::Create(end_bb, cmp_low_bb, icmp_inv_cmp, inv_cmp_bb);
797 
798       PN = PHINode::Create(Int1Ty, 3);
799       PN->addIncoming(icmp_low, cmp_low_bb);
800       PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb);
801       PN->addIncoming(ConstantInt::get(Int1Ty, 0), inv_cmp_bb);
802       break;
803 
804     }
805 
806     default:
807       if (!be_quiet)
808         fprintf(stderr, "Error: split-compare: should not happen\n");
809       return false;
810 
811   }
812 
813   BasicBlock::iterator ii(cmp_inst);
814 #if LLVM_MAJOR >= 16
815   ReplaceInstWithInst(cmp_inst->getParent(), ii, PN);
816 #else
817   ReplaceInstWithInst(cmp_inst->getParent()->getInstList(), ii, PN);
818 #endif
819 
820   // We split the comparison into low and high. If this isn't our target
821   // bitwidth we recursively split the low and high parts again until we have
822   // target bitwidth.
823   if ((bitw / 2) > target_bitwidth) {
824 
825     worklist.push_back(icmp_high);
826     worklist.push_back(icmp_low);
827 
828   }
829 
830   return true;
831 
832 }
833 
simplifyAndSplit(CmpInst * I,Module & M)834 bool SplitComparesTransform::simplifyAndSplit(CmpInst *I, Module &M) {
835 
836   CmpWorklist worklist;
837 
838   auto op0 = I->getOperand(0);
839   auto op1 = I->getOperand(1);
840   if (!op0 || !op1) { return false; }
841   auto op0Ty = dyn_cast<IntegerType>(op0->getType());
842   if (!op0Ty || !isa<IntegerType>(op1->getType())) { return true; }
843 
844   unsigned bitw = op0Ty->getBitWidth();
845 
846 #ifdef VERIFY_TOO_MUCH
847   auto F = I->getParent()->getParent();
848 #endif
849 
850   // we run the comparison simplification on all compares regardless of their
851   // bitwidth.
852   if (I->getPredicate() == CmpInst::ICMP_UGE ||
853       I->getPredicate() == CmpInst::ICMP_SGE ||
854       I->getPredicate() == CmpInst::ICMP_ULE ||
855       I->getPredicate() == CmpInst::ICMP_SLE) {
856 
857     if (!simplifyOrEqualsCompare(I, M, worklist)) {
858 
859       reportError(
860           "Failed to simplify inequality or equals comparison "
861           "(UGE,SGE,ULE,SLE)",
862           I, M);
863 
864     }
865 
866   } else if (I->getPredicate() == CmpInst::ICMP_SGT ||
867 
868              I->getPredicate() == CmpInst::ICMP_SLT) {
869 
870     if (!simplifySignedCompare(I, M, worklist)) {
871 
872       reportError("Failed to simplify signed comparison (SGT,SLT)", I, M);
873 
874     }
875 
876   }
877 
878 #ifdef VERIFY_TOO_MUCH
879   if (verifyFunction(*F, &errs())) {
880 
881     reportError("simpliyfing compare lead to broken function", nullptr, M);
882 
883   }
884 
885 #endif
886 
887   // the simplification methods replace the original CmpInst and push the
888   // resulting new CmpInst into the worklist. If the worklist is empty then
889   // we only have to split the original CmpInst.
890   if (worklist.size() == 0) { worklist.push_back(I); }
891 
892   while (!worklist.empty()) {
893 
894     CmpInst *cmp = worklist.pop_back_val();
895     // we split the simplified compares into comparisons with smaller bitwidths
896     // if they are larger than our target_bitwidth.
897     if (bitw > target_bitwidth) {
898 
899       if (!splitCompare(cmp, M, worklist)) {
900 
901         reportError("Failed to split comparison", cmp, M);
902 
903       }
904 
905 #ifdef VERIFY_TOO_MUCH
906       if (verifyFunction(*F, &errs())) {
907 
908         reportError("splitting compare lead to broken function", nullptr, M);
909 
910       }
911 
912 #endif
913 
914     }
915 
916   }
917 
918   count++;
919   return true;
920 
921 }
922 
nextPowerOfTwo(size_t in)923 size_t SplitComparesTransform::nextPowerOfTwo(size_t in) {
924 
925   --in;
926   in |= in >> 1;
927   in |= in >> 2;
928   in |= in >> 4;
929   //  in |= in >> 8;
930   //  in |= in >> 16;
931   return in + 1;
932 
933 }
934 
935 /* splits fcmps into two nested fcmps with sign compare and the rest */
splitFPCompares(Module & M)936 size_t SplitComparesTransform::splitFPCompares(Module &M) {
937 
938   size_t count = 0;
939 
940   LLVMContext &C = M.getContext();
941 
942 #if LLVM_VERSION_MAJOR >= 4 || \
943     (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 7)
944   const DataLayout &dl = M.getDataLayout();
945 
946   /* define unions with floating point and (sign, exponent, mantissa)  triples
947    */
948   if (dl.isLittleEndian()) {
949 
950   } else if (dl.isBigEndian()) {
951 
952   } else {
953 
954     return count;
955 
956   }
957 
958 #endif
959 
960   std::vector<CmpInst *> fcomps;
961 
962   /* get all EQ, NE, GT, and LT fcmps. if the other two
963    * functions were executed only these four predicates should exist */
964   for (auto &F : M) {
965 
966     if (!isInInstrumentList(&F, MNAME)) continue;
967 
968     for (auto &BB : F) {
969 
970       for (auto &IN : BB) {
971 
972         CmpInst *selectcmpInst = nullptr;
973 
974         if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) {
975 
976           if (selectcmpInst->getPredicate() == CmpInst::FCMP_OEQ ||
977               selectcmpInst->getPredicate() == CmpInst::FCMP_UEQ ||
978               selectcmpInst->getPredicate() == CmpInst::FCMP_ONE ||
979               selectcmpInst->getPredicate() == CmpInst::FCMP_UNE ||
980               selectcmpInst->getPredicate() == CmpInst::FCMP_UGT ||
981               selectcmpInst->getPredicate() == CmpInst::FCMP_OGT ||
982               selectcmpInst->getPredicate() == CmpInst::FCMP_ULT ||
983               selectcmpInst->getPredicate() == CmpInst::FCMP_OLT) {
984 
985             auto op0 = selectcmpInst->getOperand(0);
986             auto op1 = selectcmpInst->getOperand(1);
987 
988             Type *TyOp0 = op0->getType();
989             Type *TyOp1 = op1->getType();
990 
991             if (TyOp0 != TyOp1) { continue; }
992 
993             if (TyOp0->isArrayTy() || TyOp0->isVectorTy()) { continue; }
994 
995             fcomps.push_back(selectcmpInst);
996 
997           }
998 
999         }
1000 
1001       }
1002 
1003     }
1004 
1005   }
1006 
1007   if (!fcomps.size()) { return count; }
1008 
1009   IntegerType *Int1Ty = IntegerType::getInt1Ty(C);
1010 
1011   for (auto &FcmpInst : fcomps) {
1012 
1013     BasicBlock *bb = FcmpInst->getParent();
1014 
1015     auto op0 = FcmpInst->getOperand(0);
1016     auto op1 = FcmpInst->getOperand(1);
1017 
1018     unsigned op_size;
1019     op_size = op0->getType()->getPrimitiveSizeInBits();
1020 
1021     if (op_size != op1->getType()->getPrimitiveSizeInBits()) { continue; }
1022 
1023     const unsigned int sizeInBits = op0->getType()->getPrimitiveSizeInBits();
1024 
1025     // BUG FIXME TODO: u64 does not work for > 64 bit ... e.g. 80 and 128 bit
1026     if (sizeInBits > 64) { continue; }
1027 
1028     IntegerType       *intType = IntegerType::get(C, op_size);
1029     const unsigned int precision = sizeInBits == 32    ? 24
1030                                    : sizeInBits == 64  ? 53
1031                                    : sizeInBits == 128 ? 113
1032                                    : sizeInBits == 16  ? 11
1033                                    : sizeInBits == 80  ? 65
1034                                                        : sizeInBits - 8;
1035 
1036     const unsigned           shiftR_exponent = precision - 1;
1037     const unsigned long long mask_fraction =
1038         (1ULL << (shiftR_exponent - 1)) | ((1ULL << (shiftR_exponent - 1)) - 1);
1039     const unsigned long long mask_exponent =
1040         (1ULL << (sizeInBits - precision)) - 1;
1041 
1042     // round up sizes to the next power of two
1043     // this should help with integer compare splitting
1044     size_t exTySizeBytes = ((sizeInBits - precision + 7) >> 3);
1045     size_t frTySizeBytes = ((precision - 1ULL + 7) >> 3);
1046 
1047     IntegerType *IntExponentTy =
1048         IntegerType::get(C, nextPowerOfTwo(exTySizeBytes) << 3);
1049     IntegerType *IntFractionTy =
1050         IntegerType::get(C, nextPowerOfTwo(frTySizeBytes) << 3);
1051 
1052     //    errs() << "Fractions: IntFractionTy size " <<
1053     //     IntFractionTy->getPrimitiveSizeInBits() << ", op_size " << op_size <<
1054     //     ", mask " << mask_fraction <<
1055     //     ", precision " << precision << "\n";
1056 
1057     BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(FcmpInst));
1058 
1059     /* create the integers from floats directly */
1060     Instruction *bpre_op0, *bpre_op1;
1061     bpre_op0 = CastInst::Create(Instruction::BitCast, op0,
1062                                 IntegerType::get(C, op_size));
1063 #if LLVM_MAJOR >= 16
1064     bpre_op0->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
1065 #else
1066     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
1067                              bpre_op0);
1068 #endif
1069 
1070     bpre_op1 = CastInst::Create(Instruction::BitCast, op1,
1071                                 IntegerType::get(C, op_size));
1072 #if LLVM_MAJOR >= 16
1073     bpre_op1->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
1074 #else
1075     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
1076                              bpre_op1);
1077 #endif
1078 
1079     /* Check if any operand is NaN.
1080      * If so, all comparisons except unequal (which yields true) yield false */
1081 
1082     /* build mask for NaN */
1083     const unsigned long long NaN_lowend = mask_exponent << precision;
1084     //    errs() << "Fractions: IntFractionTy size " <<
1085     //     IntFractionTy->getPrimitiveSizeInBits() << ", op_size " << op_size <<
1086     //     ", mask_fraction 0x";
1087     //    errs().write_hex(mask_fraction);
1088     //    errs() << ", precision " << precision <<
1089     //     ", NaN_lowend 0x";
1090     //    errs().write_hex(NaN_lowend); errs() << "\n";
1091 
1092     /* Check op0 for NaN */
1093     /* Shift left 1 Bit, ignore sign bit */
1094     Instruction *nan_op0, *nan_op1;
1095     nan_op0 = BinaryOperator::Create(Instruction::Shl, bpre_op0,
1096                                      ConstantInt::get(bpre_op0->getType(), 1));
1097     /* Check op1 for NaN */
1098     /* Shift right 1 Bit, ignore sign bit */
1099     nan_op1 = BinaryOperator::Create(Instruction::Shl, bpre_op1,
1100                                      ConstantInt::get(bpre_op1->getType(), 1));
1101     /* compare to NaN interval */
1102     Instruction *is_op0_nan =
1103         CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, nan_op0,
1104                         ConstantInt::get(intType, NaN_lowend));
1105     /* compare to NaN interval */
1106     Instruction *is_op1_nan =
1107         CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, nan_op1,
1108                         ConstantInt::get(intType, NaN_lowend));
1109     /* combine checks */
1110     Instruction *is_nan =
1111         BinaryOperator::Create(Instruction::Or, is_op0_nan, is_op1_nan);
1112 #if LLVM_MAJOR >= 16
1113     nan_op0->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
1114     is_op0_nan->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
1115     nan_op1->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
1116     is_op1_nan->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
1117     is_nan->insertInto(bb, BasicBlock::iterator(bb->getTerminator()));
1118 #else
1119     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
1120                              nan_op0);
1121 
1122     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
1123                              is_op0_nan);
1124 
1125     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
1126                              nan_op1);
1127 
1128     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()),
1129                              is_op1_nan);
1130 
1131     bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), is_nan);
1132 #endif
1133 
1134     /* the result of the comparison, when at least one op is NaN
1135        is true only for the "NOT EQUAL" predicates. */
1136     bool NaNcmp_result = FcmpInst->getPredicate() == CmpInst::FCMP_ONE ||
1137                          FcmpInst->getPredicate() == CmpInst::FCMP_UNE;
1138 
1139     BasicBlock *nonan_bb =
1140         BasicBlock::Create(C, "noNaN", end_bb->getParent(), end_bb);
1141 
1142     BranchInst::Create(end_bb, nonan_bb);
1143 
1144     auto term = bb->getTerminator();
1145     /* if no operand is NaN goto nonan_bb else to handleNaN_bb */
1146     BranchInst::Create(end_bb, nonan_bb, is_nan, bb);
1147     term->eraseFromParent();
1148 
1149     /*** now working in nonan_bb ***/
1150 
1151     /* Treat -0.0 as equal to +0.0, that is for -0.0 make it +0.0 */
1152     Instruction             *b_op0, *b_op1;
1153     Instruction             *isMzero_op0, *isMzero_op1;
1154     const unsigned long long MinusZero = 1UL << (sizeInBits - 1U);
1155     const unsigned long long PlusZero = 0;
1156 
1157     isMzero_op0 = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, bpre_op0,
1158                                   ConstantInt::get(intType, MinusZero));
1159     isMzero_op1 = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, bpre_op1,
1160                                   ConstantInt::get(intType, MinusZero));
1161     b_op0 = SelectInst::Create(isMzero_op0, ConstantInt::get(intType, PlusZero),
1162                                bpre_op0);
1163     b_op1 = SelectInst::Create(isMzero_op1, ConstantInt::get(intType, PlusZero),
1164                                bpre_op1);
1165 #if LLVM_MAJOR >= 16
1166     isMzero_op0->insertInto(nonan_bb,
1167                             BasicBlock::iterator(nonan_bb->getTerminator()));
1168     isMzero_op1->insertInto(nonan_bb,
1169                             BasicBlock::iterator(nonan_bb->getTerminator()));
1170     b_op0->insertInto(nonan_bb,
1171                       BasicBlock::iterator(nonan_bb->getTerminator()));
1172     b_op1->insertInto(nonan_bb,
1173                       BasicBlock::iterator(nonan_bb->getTerminator()));
1174 #else
1175     nonan_bb->getInstList().insert(
1176         BasicBlock::iterator(nonan_bb->getTerminator()), isMzero_op0);
1177 
1178     nonan_bb->getInstList().insert(
1179         BasicBlock::iterator(nonan_bb->getTerminator()), isMzero_op1);
1180 
1181     nonan_bb->getInstList().insert(
1182         BasicBlock::iterator(nonan_bb->getTerminator()), b_op0);
1183 
1184     nonan_bb->getInstList().insert(
1185         BasicBlock::iterator(nonan_bb->getTerminator()), b_op1);
1186 #endif
1187 
1188     /* isolate signs of value of floating point type */
1189 
1190     /* create a 1 bit compare for the sign bit. to do this shift and trunc
1191      * the original operands so only the first bit remains.*/
1192     Instruction *s_s0, *t_s0, *s_s1, *t_s1, *icmp_sign_bit;
1193 
1194     s_s0 =
1195         BinaryOperator::Create(Instruction::LShr, b_op0,
1196                                ConstantInt::get(b_op0->getType(), op_size - 1));
1197     s_s1 =
1198         BinaryOperator::Create(Instruction::LShr, b_op1,
1199                                ConstantInt::get(b_op1->getType(), op_size - 1));
1200     t_s0 = new TruncInst(s_s0, Int1Ty);
1201     t_s1 = new TruncInst(s_s1, Int1Ty);
1202     /* compare of the sign bits */
1203     icmp_sign_bit =
1204         CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_s0, t_s1);
1205 #if LLVM_MAJOR >= 16
1206     s_s0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
1207     t_s0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
1208     s_s1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
1209     t_s1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator()));
1210     icmp_sign_bit->insertInto(nonan_bb,
1211                               BasicBlock::iterator(nonan_bb->getTerminator()));
1212 #else
1213     nonan_bb->getInstList().insert(
1214         BasicBlock::iterator(nonan_bb->getTerminator()), s_s0);
1215     nonan_bb->getInstList().insert(
1216         BasicBlock::iterator(nonan_bb->getTerminator()), t_s0);
1217 
1218     nonan_bb->getInstList().insert(
1219         BasicBlock::iterator(nonan_bb->getTerminator()), s_s1);
1220     nonan_bb->getInstList().insert(
1221         BasicBlock::iterator(nonan_bb->getTerminator()), t_s1);
1222 
1223     nonan_bb->getInstList().insert(
1224         BasicBlock::iterator(nonan_bb->getTerminator()), icmp_sign_bit);
1225 #endif
1226 
1227     /* create a new basic block which is executed if the signedness bits are
1228      * equal */
1229     BasicBlock *signequal_bb =
1230         BasicBlock::Create(C, "signequal", end_bb->getParent(), end_bb);
1231 
1232     BranchInst::Create(end_bb, signequal_bb);
1233 
1234     /* create a new bb which is executed if exponents are satisfying the compare
1235      */
1236     BasicBlock *middle_bb =
1237         BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
1238 
1239     BranchInst::Create(end_bb, middle_bb);
1240 
1241     term = nonan_bb->getTerminator();
1242     /* if the signs are different goto end_bb else to signequal_bb */
1243     BranchInst::Create(signequal_bb, end_bb, icmp_sign_bit, nonan_bb);
1244     term->eraseFromParent();
1245 
1246     /* insert code for equal signs */
1247 
1248     /* isolate the exponents */
1249     Instruction *s_e0, *m_e0, *t_e0, *s_e1, *m_e1, *t_e1;
1250 
1251     s_e0 = BinaryOperator::Create(
1252         Instruction::LShr, b_op0,
1253         ConstantInt::get(b_op0->getType(), shiftR_exponent));
1254     s_e1 = BinaryOperator::Create(
1255         Instruction::LShr, b_op1,
1256         ConstantInt::get(b_op1->getType(), shiftR_exponent));
1257 #if LLVM_MAJOR >= 16
1258     s_e0->insertInto(signequal_bb,
1259                      BasicBlock::iterator(signequal_bb->getTerminator()));
1260     s_e1->insertInto(signequal_bb,
1261                      BasicBlock::iterator(signequal_bb->getTerminator()));
1262 #else
1263     signequal_bb->getInstList().insert(
1264         BasicBlock::iterator(signequal_bb->getTerminator()), s_e0);
1265     signequal_bb->getInstList().insert(
1266         BasicBlock::iterator(signequal_bb->getTerminator()), s_e1);
1267 #endif
1268 
1269     t_e0 = new TruncInst(s_e0, IntExponentTy);
1270     t_e1 = new TruncInst(s_e1, IntExponentTy);
1271 #if LLVM_MAJOR >= 16
1272     t_e0->insertInto(signequal_bb,
1273                      BasicBlock::iterator(signequal_bb->getTerminator()));
1274     t_e1->insertInto(signequal_bb,
1275                      BasicBlock::iterator(signequal_bb->getTerminator()));
1276 #else
1277     signequal_bb->getInstList().insert(
1278         BasicBlock::iterator(signequal_bb->getTerminator()), t_e0);
1279     signequal_bb->getInstList().insert(
1280         BasicBlock::iterator(signequal_bb->getTerminator()), t_e1);
1281 #endif
1282 
1283     if (sizeInBits - precision < exTySizeBytes * 8) {
1284 
1285       m_e0 = BinaryOperator::Create(
1286           Instruction::And, t_e0,
1287           ConstantInt::get(t_e0->getType(), mask_exponent));
1288       m_e1 = BinaryOperator::Create(
1289           Instruction::And, t_e1,
1290           ConstantInt::get(t_e1->getType(), mask_exponent));
1291 #if LLVM_MAJOR >= 16
1292       m_e0->insertInto(signequal_bb,
1293                        BasicBlock::iterator(signequal_bb->getTerminator()));
1294       m_e1->insertInto(signequal_bb,
1295                        BasicBlock::iterator(signequal_bb->getTerminator()));
1296 #else
1297       signequal_bb->getInstList().insert(
1298           BasicBlock::iterator(signequal_bb->getTerminator()), m_e0);
1299       signequal_bb->getInstList().insert(
1300           BasicBlock::iterator(signequal_bb->getTerminator()), m_e1);
1301 #endif
1302 
1303     } else {
1304 
1305       m_e0 = t_e0;
1306       m_e1 = t_e1;
1307 
1308     }
1309 
1310     /* compare the exponents of the operands */
1311     Instruction *icmp_exponents_equal;
1312     Instruction *icmp_exponent_result;
1313     BasicBlock  *signequal2_bb = signequal_bb;
1314     switch (FcmpInst->getPredicate()) {
1315 
1316       case CmpInst::FCMP_UEQ:
1317       case CmpInst::FCMP_OEQ:
1318         icmp_exponent_result =
1319             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1);
1320         break;
1321       case CmpInst::FCMP_ONE:
1322       case CmpInst::FCMP_UNE:
1323         icmp_exponent_result =
1324             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, m_e0, m_e1);
1325         break;
1326       /* compare the exponents of the operands (signs are equal)
1327        * if exponents are equal -> proceed to mantissa comparison
1328        * else get result depending on sign
1329        */
1330       case CmpInst::FCMP_OGT:
1331       case CmpInst::FCMP_UGT:
1332         Instruction *icmp_exponent;
1333         icmp_exponents_equal =
1334             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1);
1335 #if LLVM_MAJOR >= 16
1336         icmp_exponents_equal->insertInto(
1337             signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator()));
1338 #else
1339         signequal_bb->getInstList().insert(
1340             BasicBlock::iterator(signequal_bb->getTerminator()),
1341             icmp_exponents_equal);
1342 #endif
1343 
1344         // shortcut for unequal exponents
1345         signequal2_bb = signequal_bb->splitBasicBlock(
1346             BasicBlock::iterator(signequal_bb->getTerminator()));
1347 
1348         /* if the exponents are equal goto middle_bb else to signequal2_bb */
1349         term = signequal_bb->getTerminator();
1350         BranchInst::Create(middle_bb, signequal2_bb, icmp_exponents_equal,
1351                            signequal_bb);
1352         term->eraseFromParent();
1353 
1354         icmp_exponent =
1355             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, m_e0, m_e1);
1356 #if LLVM_MAJOR >= 16
1357         icmp_exponent->insertInto(
1358             signequal2_bb,
1359             BasicBlock::iterator(signequal2_bb->getTerminator()));
1360 #else
1361         signequal2_bb->getInstList().insert(
1362             BasicBlock::iterator(signequal2_bb->getTerminator()),
1363             icmp_exponent);
1364 #endif
1365         icmp_exponent_result =
1366             BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
1367         break;
1368       case CmpInst::FCMP_OLT:
1369       case CmpInst::FCMP_ULT:
1370         icmp_exponents_equal =
1371             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1);
1372 #if LLVM_MAJOR >= 16
1373         icmp_exponents_equal->insertInto(
1374             signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator()));
1375 #else
1376         signequal_bb->getInstList().insert(
1377             BasicBlock::iterator(signequal_bb->getTerminator()),
1378             icmp_exponents_equal);
1379 #endif
1380 
1381         // shortcut for unequal exponents
1382         signequal2_bb = signequal_bb->splitBasicBlock(
1383             BasicBlock::iterator(signequal_bb->getTerminator()));
1384 
1385         /* if the exponents are equal goto middle_bb else to signequal2_bb */
1386         term = signequal_bb->getTerminator();
1387         BranchInst::Create(middle_bb, signequal2_bb, icmp_exponents_equal,
1388                            signequal_bb);
1389         term->eraseFromParent();
1390 
1391         icmp_exponent =
1392             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, m_e0, m_e1);
1393 #if LLVM_MAJOR >= 16
1394         icmp_exponent->insertInto(
1395             signequal2_bb,
1396             BasicBlock::iterator(signequal2_bb->getTerminator()));
1397 #else
1398         signequal2_bb->getInstList().insert(
1399             BasicBlock::iterator(signequal2_bb->getTerminator()),
1400             icmp_exponent);
1401 #endif
1402         icmp_exponent_result =
1403             BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
1404         break;
1405       default:
1406         continue;
1407 
1408     }
1409 
1410 #if LLVM_MAJOR >= 16
1411     icmp_exponent_result->insertInto(
1412         signequal2_bb, BasicBlock::iterator(signequal2_bb->getTerminator()));
1413 #else
1414     signequal2_bb->getInstList().insert(
1415         BasicBlock::iterator(signequal2_bb->getTerminator()),
1416         icmp_exponent_result);
1417 #endif
1418 
1419     {
1420 
1421       term = signequal2_bb->getTerminator();
1422 
1423       switch (FcmpInst->getPredicate()) {
1424 
1425         case CmpInst::FCMP_UEQ:
1426         case CmpInst::FCMP_OEQ:
1427           /* if the exponents are satifying the compare do a fraction cmp in
1428            * middle_bb */
1429           BranchInst::Create(middle_bb, end_bb, icmp_exponent_result,
1430                              signequal2_bb);
1431           break;
1432         case CmpInst::FCMP_ONE:
1433         case CmpInst::FCMP_UNE:
1434           /* if the exponents are satifying the compare do a fraction cmp in
1435            * middle_bb */
1436           BranchInst::Create(end_bb, middle_bb, icmp_exponent_result,
1437                              signequal2_bb);
1438           break;
1439         case CmpInst::FCMP_OGT:
1440         case CmpInst::FCMP_UGT:
1441         case CmpInst::FCMP_OLT:
1442         case CmpInst::FCMP_ULT:
1443           BranchInst::Create(end_bb, signequal2_bb);
1444           break;
1445         default:
1446           continue;
1447 
1448       }
1449 
1450       term->eraseFromParent();
1451 
1452     }
1453 
1454     /* isolate the mantissa aka fraction */
1455     Instruction *t_f0, *t_f1;
1456     bool         needTrunc = IntFractionTy->getPrimitiveSizeInBits() < op_size;
1457 
1458     if (precision - 1 < frTySizeBytes * 8) {
1459 
1460       Instruction *m_f0, *m_f1;
1461       m_f0 = BinaryOperator::Create(
1462           Instruction::And, b_op0,
1463           ConstantInt::get(b_op0->getType(), mask_fraction));
1464       m_f1 = BinaryOperator::Create(
1465           Instruction::And, b_op1,
1466           ConstantInt::get(b_op1->getType(), mask_fraction));
1467 #if LLVM_MAJOR >= 16
1468       m_f0->insertInto(middle_bb,
1469                        BasicBlock::iterator(middle_bb->getTerminator()));
1470       m_f1->insertInto(middle_bb,
1471                        BasicBlock::iterator(middle_bb->getTerminator()));
1472 #else
1473       middle_bb->getInstList().insert(
1474           BasicBlock::iterator(middle_bb->getTerminator()), m_f0);
1475       middle_bb->getInstList().insert(
1476           BasicBlock::iterator(middle_bb->getTerminator()), m_f1);
1477 #endif
1478 
1479       if (needTrunc) {
1480 
1481         t_f0 = new TruncInst(m_f0, IntFractionTy);
1482         t_f1 = new TruncInst(m_f1, IntFractionTy);
1483 #if LLVM_MAJOR >= 16
1484         t_f0->insertInto(middle_bb,
1485                          BasicBlock::iterator(middle_bb->getTerminator()));
1486         t_f1->insertInto(middle_bb,
1487                          BasicBlock::iterator(middle_bb->getTerminator()));
1488 #else
1489         middle_bb->getInstList().insert(
1490             BasicBlock::iterator(middle_bb->getTerminator()), t_f0);
1491         middle_bb->getInstList().insert(
1492             BasicBlock::iterator(middle_bb->getTerminator()), t_f1);
1493 #endif
1494 
1495       } else {
1496 
1497         t_f0 = m_f0;
1498         t_f1 = m_f1;
1499 
1500       }
1501 
1502     } else {
1503 
1504       if (needTrunc) {
1505 
1506         t_f0 = new TruncInst(b_op0, IntFractionTy);
1507         t_f1 = new TruncInst(b_op1, IntFractionTy);
1508 #if LLVM_MAJOR >= 16
1509         t_f0->insertInto(middle_bb,
1510                          BasicBlock::iterator(middle_bb->getTerminator()));
1511         t_f1->insertInto(middle_bb,
1512                          BasicBlock::iterator(middle_bb->getTerminator()));
1513 #else
1514         middle_bb->getInstList().insert(
1515             BasicBlock::iterator(middle_bb->getTerminator()), t_f0);
1516         middle_bb->getInstList().insert(
1517             BasicBlock::iterator(middle_bb->getTerminator()), t_f1);
1518 #endif
1519 
1520       } else {
1521 
1522         t_f0 = b_op0;
1523         t_f1 = b_op1;
1524 
1525       }
1526 
1527     }
1528 
1529     /* compare the fractions of the operands */
1530     Instruction *icmp_fraction_result;
1531     BasicBlock  *middle2_bb = middle_bb;
1532     PHINode     *PN2 = nullptr;
1533     switch (FcmpInst->getPredicate()) {
1534 
1535       case CmpInst::FCMP_UEQ:
1536       case CmpInst::FCMP_OEQ:
1537         icmp_fraction_result =
1538             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_f0, t_f1);
1539 #if LLVM_MAJOR >= 16
1540         icmp_fraction_result->insertInto(
1541             middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator()));
1542 #else
1543         middle2_bb->getInstList().insert(
1544             BasicBlock::iterator(middle2_bb->getTerminator()),
1545             icmp_fraction_result);
1546 #endif
1547 
1548         break;
1549       case CmpInst::FCMP_UNE:
1550       case CmpInst::FCMP_ONE:
1551         icmp_fraction_result =
1552             CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, t_f0, t_f1);
1553 #if LLVM_MAJOR >= 16
1554         icmp_fraction_result->insertInto(
1555             middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator()));
1556 #else
1557         middle2_bb->getInstList().insert(
1558             BasicBlock::iterator(middle2_bb->getTerminator()),
1559             icmp_fraction_result);
1560 #endif
1561 
1562         break;
1563       case CmpInst::FCMP_OGT:
1564       case CmpInst::FCMP_UGT:
1565       case CmpInst::FCMP_OLT:
1566       case CmpInst::FCMP_ULT: {
1567 
1568         Instruction *icmp_fraction_result2;
1569 
1570         middle2_bb = middle_bb->splitBasicBlock(
1571             BasicBlock::iterator(middle_bb->getTerminator()));
1572 
1573         BasicBlock *negative_bb = BasicBlock::Create(
1574             C, "negative_value", middle2_bb->getParent(), middle2_bb);
1575         BasicBlock *positive_bb = BasicBlock::Create(
1576             C, "positive_value", negative_bb->getParent(), negative_bb);
1577 
1578         if (FcmpInst->getPredicate() == CmpInst::FCMP_OGT ||
1579             FcmpInst->getPredicate() == CmpInst::FCMP_UGT) {
1580 
1581           icmp_fraction_result =
1582               CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1);
1583           icmp_fraction_result2 =
1584               CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1);
1585 #if LLVM_MAJOR >= 16
1586           icmp_fraction_result->insertInto(negative_bb, negative_bb->end());
1587           icmp_fraction_result2->insertInto(positive_bb, positive_bb->end());
1588 #else
1589           negative_bb->getInstList().push_back(icmp_fraction_result);
1590           positive_bb->getInstList().push_back(icmp_fraction_result2);
1591 #endif
1592 
1593         } else {
1594 
1595           icmp_fraction_result =
1596               CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1);
1597           icmp_fraction_result2 =
1598               CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1);
1599 #if LLVM_MAJOR >= 16
1600           icmp_fraction_result->insertInto(negative_bb, negative_bb->end());
1601           icmp_fraction_result2->insertInto(positive_bb, positive_bb->end());
1602 #else
1603           negative_bb->getInstList().push_back(icmp_fraction_result);
1604           positive_bb->getInstList().push_back(icmp_fraction_result2);
1605 #endif
1606 
1607         }
1608 
1609         BranchInst::Create(middle2_bb, negative_bb);
1610         BranchInst::Create(middle2_bb, positive_bb);
1611 
1612         term = middle_bb->getTerminator();
1613         BranchInst::Create(negative_bb, positive_bb, t_s0, middle_bb);
1614         term->eraseFromParent();
1615 
1616         PN2 = PHINode::Create(Int1Ty, 2, "");
1617         PN2->addIncoming(icmp_fraction_result, negative_bb);
1618         PN2->addIncoming(icmp_fraction_result2, positive_bb);
1619 #if LLVM_MAJOR >= 16
1620         PN2->insertInto(middle2_bb,
1621                         BasicBlock::iterator(middle2_bb->getTerminator()));
1622 #else
1623         middle2_bb->getInstList().insert(
1624             BasicBlock::iterator(middle2_bb->getTerminator()), PN2);
1625 #endif
1626 
1627       } break;
1628 
1629       default:
1630         continue;
1631 
1632     }
1633 
1634     PHINode *PN = PHINode::Create(Int1Ty, 4, "");
1635 
1636     switch (FcmpInst->getPredicate()) {
1637 
1638       case CmpInst::FCMP_UEQ:
1639       case CmpInst::FCMP_OEQ:
1640         /* unequal signs cannot be equal values */
1641         /* goto false branch */
1642         PN->addIncoming(ConstantInt::get(Int1Ty, 0), nonan_bb);
1643         /* unequal exponents cannot be equal values, too */
1644         PN->addIncoming(ConstantInt::get(Int1Ty, 0), signequal_bb);
1645         /* fractions comparison */
1646         PN->addIncoming(icmp_fraction_result, middle2_bb);
1647         /* NaNs */
1648         PN->addIncoming(ConstantInt::get(Int1Ty, NaNcmp_result), bb);
1649         break;
1650       case CmpInst::FCMP_ONE:
1651       case CmpInst::FCMP_UNE:
1652         /* unequal signs are unequal values */
1653         /* goto true branch */
1654         PN->addIncoming(ConstantInt::get(Int1Ty, 1), nonan_bb);
1655         /* unequal exponents are unequal values, too */
1656         PN->addIncoming(icmp_exponent_result, signequal_bb);
1657         /* fractions comparison */
1658         PN->addIncoming(icmp_fraction_result, middle2_bb);
1659         /* NaNs */
1660         PN->addIncoming(ConstantInt::get(Int1Ty, NaNcmp_result), bb);
1661         break;
1662       case CmpInst::FCMP_OGT:
1663       case CmpInst::FCMP_UGT:
1664         /* if op1 is negative goto true branch,
1665            else go on comparing */
1666         PN->addIncoming(t_s1, nonan_bb);
1667         PN->addIncoming(icmp_exponent_result, signequal2_bb);
1668         PN->addIncoming(PN2, middle2_bb);
1669         /* NaNs */
1670         PN->addIncoming(ConstantInt::get(Int1Ty, NaNcmp_result), bb);
1671         break;
1672       case CmpInst::FCMP_OLT:
1673       case CmpInst::FCMP_ULT:
1674         /* if op0 is negative goto true branch,
1675            else go on comparing */
1676         PN->addIncoming(t_s0, nonan_bb);
1677         PN->addIncoming(icmp_exponent_result, signequal2_bb);
1678         PN->addIncoming(PN2, middle2_bb);
1679         /* NaNs */
1680         PN->addIncoming(ConstantInt::get(Int1Ty, NaNcmp_result), bb);
1681         break;
1682       default:
1683         continue;
1684 
1685     }
1686 
1687     BasicBlock::iterator ii(FcmpInst);
1688 #if LLVM_MAJOR >= 16
1689     ReplaceInstWithInst(FcmpInst->getParent(), ii, PN);
1690 #else
1691     ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
1692 #endif
1693     ++count;
1694 
1695   }
1696 
1697   return count;
1698 
1699 }
1700 
1701 #if LLVM_MAJOR >= 11
run(Module & M,ModuleAnalysisManager & MAM)1702 PreservedAnalyses SplitComparesTransform::run(Module                &M,
1703                                               ModuleAnalysisManager &MAM) {
1704 
1705 #else
1706 bool SplitComparesTransform::runOnModule(Module &M) {
1707 
1708 #endif
1709 
1710   if ((isatty(2) && getenv("AFL_QUIET") == NULL) ||
1711       getenv("AFL_DEBUG") != NULL) {
1712 
1713     errs() << "Split-compare-newpass by [email protected], extended by "
1714               "[email protected] (splitting icmp to "
1715            << target_bitwidth << " bit)\n";
1716 
1717     if (getenv("AFL_DEBUG") != NULL && !debug) { debug = 1; }
1718 
1719   } else {
1720 
1721     be_quiet = 1;
1722 
1723   }
1724 
1725   char *bitw_env = getenv("AFL_LLVM_LAF_SPLIT_COMPARES_BITW");
1726   if (!bitw_env) bitw_env = getenv("LAF_SPLIT_COMPARES_BITW");
1727   if (bitw_env) { target_bitwidth = atoi(bitw_env); }
1728 
1729   if (getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) { enableFPSplit = true; }
1730 
1731   bool split_comp = false;
1732 
1733   if (getenv("AFL_LLVM_LAF_SPLIT_COMPARES")) {
1734 
1735 #if LLVM_MAJOR == 17
1736     if (!be_quiet)
1737       fprintf(stderr,
1738               "WARNING: AFL++ splitting integer comparisons is disabled in "
1739               "LLVM 17 due bugs, switch to 16 or 18!\n");
1740 #else
1741     split_comp = true;
1742 #endif
1743 
1744   }
1745 
1746 #if LLVM_MAJOR >= 11
1747   auto PA = PreservedAnalyses::all();
1748 #endif
1749 
1750   if (enableFPSplit) {
1751 
1752     simplifyFPCompares(M);
1753     count = splitFPCompares(M);
1754 
1755     if (!be_quiet && !debug) {
1756 
1757       errs() << "Split-floatingpoint-compare-pass: " << count
1758              << " FP comparisons split\n";
1759 
1760     }
1761 
1762   }
1763 
1764   if (split_comp) {
1765 
1766     std::vector<CmpInst *> worklist;
1767     /* iterate over all functions, bbs and instruction search for all integer
1768      * compare instructions. Save them into the worklist for later. */
1769     for (auto &F : M) {
1770 
1771       if (!isInInstrumentList(&F, MNAME)) continue;
1772 
1773       for (auto &BB : F) {
1774 
1775         for (auto &IN : BB) {
1776 
1777           if (auto CI = dyn_cast<CmpInst>(&IN)) {
1778 
1779             auto op0 = CI->getOperand(0);
1780             auto op1 = CI->getOperand(1);
1781             if (!op0 || !op1) {
1782 
1783 #if LLVM_MAJOR >= 11
1784               return PA;
1785 #else
1786               return false;
1787 #endif
1788 
1789             }
1790 
1791             auto iTy1 = dyn_cast<IntegerType>(op0->getType());
1792             if (iTy1 && isa<IntegerType>(op1->getType())) {
1793 
1794               unsigned bitw = iTy1->getBitWidth();
1795               if (isSupportedBitWidth(bitw)) { worklist.push_back(CI); }
1796 
1797             }
1798 
1799           }
1800 
1801         }
1802 
1803       }
1804 
1805     }
1806 
1807     // now that we have a list of all integer comparisons we can start replacing
1808     // them with the splitted alternatives.
1809     for (auto CI : worklist) {
1810 
1811       simplifyAndSplit(CI, M);
1812 
1813     }
1814 
1815   }
1816 
1817   bool brokenDebug = false;
1818   if (verifyModule(M, &errs()
1819 #if LLVM_VERSION_MAJOR >= 4 || \
1820     (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 9)
1821                           ,
1822                    &brokenDebug  // 9th May 2016
1823 #endif
1824                    )) {
1825 
1826     reportError(
1827         "Module Verifier failed! Consider reporting a bug with the AFL++ "
1828         "project.",
1829         nullptr, M);
1830 
1831   }
1832 
1833   if (brokenDebug) {
1834 
1835     reportError("Module Verifier reported broken Debug Infos - Stripping!",
1836                 nullptr, M);
1837     StripDebugInfo(M);
1838 
1839   }
1840 
1841   if ((isatty(2) && getenv("AFL_QUIET") == NULL) ||
1842       getenv("AFL_DEBUG") != NULL) {
1843 
1844     errs() << count << " comparisons found\n";
1845 
1846   }
1847 
1848 #if LLVM_MAJOR >= 11
1849   /*  if (modified) {
1850 
1851       PA.abandon<XX_Manager>();
1852 
1853     }*/
1854 
1855   return PA;
1856 #else
1857   return true;
1858 #endif
1859 
1860 }
1861 
1862 #if LLVM_MAJOR < 11                                 /* use old pass manager */
1863 
1864 static void registerSplitComparesPass(const PassManagerBuilder &,
1865                                       legacy::PassManagerBase &PM) {
1866 
1867   PM.add(new SplitComparesTransform());
1868 
1869 }
1870 
1871 static RegisterStandardPasses RegisterSplitComparesPass(
1872     PassManagerBuilder::EP_OptimizerLast, registerSplitComparesPass);
1873 
1874 static RegisterStandardPasses RegisterSplitComparesTransPass0(
1875     PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitComparesPass);
1876 
1877   #if LLVM_VERSION_MAJOR >= 11
1878 static RegisterStandardPasses RegisterSplitComparesTransPassLTO(
1879     PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
1880     registerSplitComparesPass);
1881   #endif
1882 
1883 static RegisterPass<SplitComparesTransform> X("splitcompares",
1884                                               "AFL++ split compares",
1885                                               true /* Only looks at CFG */,
1886                                               true /* Analysis Pass */);
1887 #endif
1888 
1889