@@ -76,6 +76,7 @@ enum OperandKind {
76
76
Block,
77
77
Arg,
78
78
Global,
79
+ Predicate,
79
80
UnimplementedOperand = 255 ,
80
81
};
81
82
@@ -88,6 +89,20 @@ enum TypeKind {
88
89
UnimplementedType = 255 , // YKFIXME: Will eventually be deleted.
89
90
};
90
91
92
+ // A predicate used in a numeric comparison.
93
+ enum CmpPredicate {
94
+ PredEqual = 0 ,
95
+ PredNotEqual,
96
+ PredUnsignedGreater,
97
+ PredUnsignedGreaterEqual,
98
+ PredUnsignedLess,
99
+ PredUnsignedLessEqual,
100
+ PredSignedGreater,
101
+ PredSignedGreaterEqual,
102
+ PredSignedLess,
103
+ PredSignedLessEqual,
104
+ };
105
+
91
106
template <class T > string toString (T *X) {
92
107
string S;
93
108
raw_string_ostream SS (S);
@@ -466,6 +481,71 @@ class YkIRWriter {
466
481
InstIdx++;
467
482
}
468
483
484
+ // Serialise an LLVM predicate.
485
+ //
486
+ // Note that this can't be handled by `serialiseOperand()` as in LLVM a
487
+ // `Predicate` isn't a `Value`.
488
+ void serialisePredicateOperand (llvm::CmpInst::Predicate P) {
489
+ std::optional<CmpPredicate> LP = std::nullopt;
490
+ switch (P) {
491
+ case llvm::CmpInst::ICMP_EQ:
492
+ LP = PredEqual;
493
+ break ;
494
+ case llvm::CmpInst::ICMP_NE:
495
+ LP = PredNotEqual;
496
+ break ;
497
+ case llvm::CmpInst::ICMP_UGT:
498
+ LP = PredUnsignedGreater;
499
+ break ;
500
+ case llvm::CmpInst::ICMP_UGE:
501
+ LP = PredUnsignedGreaterEqual;
502
+ break ;
503
+ case llvm::CmpInst::ICMP_ULT:
504
+ LP = PredUnsignedLess;
505
+ break ;
506
+ case llvm::CmpInst::ICMP_ULE:
507
+ LP = PredUnsignedLessEqual;
508
+ break ;
509
+ case llvm::CmpInst::ICMP_SGT:
510
+ LP = PredSignedGreater;
511
+ break ;
512
+ case llvm::CmpInst::ICMP_SGE:
513
+ LP = PredSignedGreaterEqual;
514
+ break ;
515
+ case llvm::CmpInst::ICMP_SLT:
516
+ LP = PredSignedLess;
517
+ break ;
518
+ case llvm::CmpInst::ICMP_SLE:
519
+ LP = PredSignedLessEqual;
520
+ break ;
521
+ default :
522
+ abort (); // TODO: floating point predicates.
523
+ }
524
+ OutStreamer.emitInt8 (OperandKind::Predicate);
525
+ OutStreamer.emitInt8 (LP.value ());
526
+ }
527
+
528
+ // We use a custom lowering for ICmp, as a generic lowering misses
529
+ // the predicate.
530
+ void serialiseICmpInst (ICmpInst *I, ValueLoweringMap &VLMap, unsigned BBIdx,
531
+ unsigned &InstIdx) {
532
+ // type_index:
533
+ OutStreamer.emitSizeT (typeIndex (I->getType ()));
534
+ // opcode:
535
+ serialiseOpcode (OpCode::ICmp);
536
+ // num_operands:
537
+ OutStreamer.emitInt32 (3 );
538
+ // op1:
539
+ serialiseOperand (I, VLMap, I->getOperand (0 ));
540
+ // predicate:
541
+ serialisePredicateOperand (I->getPredicate ());
542
+ // op2:
543
+ serialiseOperand (I, VLMap, I->getOperand (1 ));
544
+
545
+ VLMap[I] = {BBIdx, InstIdx};
546
+ InstIdx++;
547
+ }
548
+
469
549
void serialiseInst (Instruction *I, ValueLoweringMap &VLMap, unsigned BBIdx,
470
550
unsigned &InstIdx) {
471
551
// Macros to help dispatch to serialisers.
@@ -484,7 +564,6 @@ class YkIRWriter {
484
564
485
565
GENERIC_INST_SERIALISE (I, LoadInst, Load)
486
566
GENERIC_INST_SERIALISE (I, StoreInst, Store)
487
- GENERIC_INST_SERIALISE (I, ICmpInst, ICmp)
488
567
GENERIC_INST_SERIALISE (I, ReturnInst, Ret)
489
568
GENERIC_INST_SERIALISE (I, llvm::InsertValueInst, InsertValue)
490
569
GENERIC_INST_SERIALISE (I, StoreInst, Store)
@@ -494,6 +573,7 @@ class YkIRWriter {
494
573
CUSTOM_INST_SERIALISE (I, BranchInst, serialiseBranchInst)
495
574
CUSTOM_INST_SERIALISE (I, GetElementPtrInst, serialiseGetElementPtr)
496
575
CUSTOM_INST_SERIALISE (I, llvm::BinaryOperator, serialiseBinaryOperation)
576
+ CUSTOM_INST_SERIALISE (I, ICmpInst, serialiseICmpInst)
497
577
498
578
// GENERIC_INST_SERIALISE and CUSTOM_INST_SERIALISE do an early return upon
499
579
// a match, so if we get here then the instruction wasn't handled.
0 commit comments