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