08c8f953bfb3e5993a74cc43c5ce1afad3ab00d2
[oota-llvm.git] / utils / TableGen / NeonEmitter.cpp
1 //===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This tablegen backend is responsible for emitting arm_neon.h, which includes
11 // a declaration and definition of each function specified by the ARM NEON 
12 // compiler interface.  See ARM document DUI0348B.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "NeonEmitter.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include <string>
21
22 using namespace llvm;
23
24 static void ParseTypes(Record *r, std::string &s,
25                        SmallVectorImpl<StringRef> &TV) {
26   const char *data = s.data();
27   int len = 0;
28   
29   for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
30     if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
31       continue;
32     
33     switch (data[len]) {
34       case 'c':
35       case 's':
36       case 'i':
37       case 'l':
38       case 'h':
39       case 'f':
40         break;
41       default:
42         throw TGError(r->getLoc(),
43                       "Unexpected letter: " + std::string(data + len, 1));
44         break;
45     }
46     TV.push_back(StringRef(data, len + 1));
47     data += len + 1;
48     len = -1;
49   }
50 }
51
52 static char Widen(const char t) {
53   switch (t) {
54     case 'c':
55       return 's';
56     case 's':
57       return 'i';
58     case 'i':
59       return 'l';
60     default: throw "unhandled type in widen!";
61   }
62   return '\0';
63 }
64
65 static char Narrow(const char t) {
66   switch (t) {
67     case 's':
68       return 'c';
69     case 'i':
70       return 's';
71     case 'l':
72       return 'i';
73     case 'f':
74       return 'h';
75     default: throw "unhandled type in widen!";
76   }
77   return '\0';
78 }
79
80 static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
81   unsigned off = 0;
82   
83   // remember quad.
84   if (ty[off] == 'Q') {
85     quad = true;
86     ++off;
87   }
88   
89   // remember poly.
90   if (ty[off] == 'P') {
91     poly = true;
92     ++off;
93   }
94   
95   // remember unsigned.
96   if (ty[off] == 'U') {
97     usgn = true;
98     ++off;
99   }
100   
101   // base type to get the type string for.
102   return ty[off];
103 }
104
105 static char ModType(const char mod, char type, bool &quad, bool &poly,
106                     bool &usgn, bool &scal, bool &cnst, bool &pntr) {
107   switch (mod) {
108     case 't':
109       if (poly) {
110         poly = false;
111         usgn = true;
112       }
113       break;
114     case 'u':
115       usgn = true;
116     case 'x':
117       poly = false;
118       if (type == 'f')
119         type = 'i';
120       break;
121     case 'f':
122       if (type == 'h')
123         quad = true;
124       type = 'f';
125       usgn = false;
126       break;
127     case 'w':
128       type = Widen(type);
129       quad = true;
130       break;
131     case 'n':
132       type = Widen(type);
133       break;
134     case 'l':
135       type = 'l';
136       scal = true;
137       usgn = true;
138       break;
139     case 's':
140       scal = true;
141       break;
142     case 'k':
143       quad = true;
144       break;
145     case 'c':
146       cnst = true;
147     case 'p':
148       usgn = false;
149       poly = false;
150       pntr = true;
151       scal = true;
152       break;
153     case 'h':
154       type = Narrow(type);
155       if (type == 'h')
156         quad = false;
157       break;
158     case 'e':
159       type = Narrow(type);
160       usgn = true;
161       break;
162     default:
163       break;
164   }
165   return type;
166 }
167
168 static std::string TypeString(const char mod, StringRef typestr,
169                               bool ret = false) {
170   bool quad = false;
171   bool poly = false;
172   bool usgn = false;
173   bool scal = false;
174   bool cnst = false;
175   bool pntr = false;
176   
177   if (mod == 'v')
178     return "void";
179   if (mod == 'i')
180     return "int";
181   
182   // base type to get the type string for.
183   char type = ClassifyType(typestr, quad, poly, usgn);
184   
185   // Based on the modifying character, change the type and width if necessary.
186   type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
187   
188   SmallString<128> s;
189   
190   if (ret)
191     s += "__neon_";
192   
193   if (usgn)
194     s.push_back('u');
195   
196   switch (type) {
197     case 'c':
198       s += poly ? "poly8" : "int8";
199       if (scal)
200         break;
201       s += quad ? "x16" : "x8";
202       break;
203     case 's':
204       s += poly ? "poly16" : "int16";
205       if (scal)
206         break;
207       s += quad ? "x8" : "x4";
208       break;
209     case 'i':
210       s += "int32";
211       if (scal)
212         break;
213       s += quad ? "x4" : "x2";
214       break;
215     case 'l':
216       s += "int64";
217       if (scal)
218         break;
219       s += quad ? "x2" : "x1";
220       break;
221     case 'h':
222       s += "float16";
223       if (scal)
224         break;
225       s += quad ? "x8" : "x4";
226       break;
227     case 'f':
228       s += "float32";
229       if (scal)
230         break;
231       s += quad ? "x4" : "x2";
232       break;
233     default:
234       throw "unhandled type!";
235       break;
236   }
237
238   if (mod == '2')
239     s += "x2";
240   if (mod == '3')
241     s += "x3";
242   if (mod == '4')
243     s += "x4";
244   
245   // Append _t, finishing the type string typedef type.
246   s += "_t";
247   
248   if (cnst)
249     s += " const";
250   
251   if (pntr)
252     s += " *";
253   
254   return s.str();
255 }
256
257 static std::string BuiltinTypeString(const char mod, StringRef typestr,
258                                      ClassKind ck, bool ret) {
259   bool quad = false;
260   bool poly = false;
261   bool usgn = false;
262   bool scal = false;
263   bool cnst = false;
264   bool pntr = false;
265   
266   if (mod == 'v')
267     return "v";
268   if (mod == 'i')
269     return "i";
270   
271   // base type to get the type string for.
272   char type = ClassifyType(typestr, quad, poly, usgn);
273   
274   // Based on the modifying character, change the type and width if necessary.
275   type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
276
277   if (pntr)
278     type = 'v';
279   
280   if (type == 'h') {
281     type = 's';
282     usgn = true;
283   }
284   usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
285
286   if (scal) {
287     SmallString<128> s;
288
289     if (usgn)
290       s.push_back('U');
291     
292     if (type == 'l')
293       s += "LLi";
294     else
295       s.push_back(type);
296  
297     if (cnst)
298       s.push_back('C');
299     if (pntr)
300       s.push_back('*');
301     return s.str();
302   }
303
304   // Since the return value must be one type, return a vector type of the
305   // appropriate width which we will bitcast.
306   if (ret) {
307     if (mod == '2')
308       return quad ? "V32c" : "V16c";
309     if (mod == '3')
310       return quad ? "V48c" : "V24c";
311     if (mod == '4')
312       return quad ? "V64c" : "V32c";
313   if (mod == 'f')
314     return quad ? "V4f" : "V2f";
315     
316     return quad ? "V16c" : "V8c";
317   }    
318
319   // Non-return array types are passed as individual vectors.
320   if (mod == '2')
321     return quad ? "V16cV16c" : "V8cV8c";
322   if (mod == '3')
323     return quad ? "V16cV16cV16c" : "V8cV8cV8c";
324   if (mod == '4')
325     return quad ? "V16cV16cV16cV16c" : "V8cV8cV8cV8c";
326   if (mod == 'f')
327     return quad ? "V4f" : "V2f";
328
329   return quad ? "V16c" : "V8c";
330 }
331
332 // Turn "vst2_lane" into "vst2q_lane_f32", etc.
333 static std::string MangleName(const std::string &name, StringRef typestr,
334                               ClassKind ck) {
335   if (name == "vcvt_f32_f16")
336     return name;
337   
338   bool quad = false;
339   bool poly = false;
340   bool usgn = false;
341   char type = ClassifyType(typestr, quad, poly, usgn);
342
343   std::string s = name;
344   
345   switch (type) {
346   case 'c':
347     switch (ck) {
348     case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
349     case ClassI: s += "_i8"; break;
350     case ClassW: s += "_8"; break;
351     default: break;
352     }
353     break;
354   case 's':
355     switch (ck) {
356     case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
357     case ClassI: s += "_i16"; break;
358     case ClassW: s += "_16"; break;
359     default: break;
360     }
361     break;
362   case 'i':
363     switch (ck) {
364     case ClassS: s += usgn ? "_u32" : "_s32"; break;
365     case ClassI: s += "_i32"; break;
366     case ClassW: s += "_32"; break;
367     default: break;
368     }
369     break;
370   case 'l':
371     switch (ck) {
372     case ClassS: s += usgn ? "_u64" : "_s64"; break;
373     case ClassI: s += "_i64"; break;
374     case ClassW: s += "_64"; break;
375     default: break;
376     }
377     break;
378   case 'h':
379     switch (ck) {
380     case ClassS:
381     case ClassI: s += "_f16"; break;
382     case ClassW: s += "_16"; break;
383     default: break;
384     }
385     break;
386   case 'f':
387     switch (ck) {
388     case ClassS:
389     case ClassI: s += "_f32"; break;
390     case ClassW: s += "_32"; break;
391     default: break;
392     }
393     break;
394   default:
395     throw "unhandled type!";
396     break;
397   }
398   if (ck == ClassB)
399     s += "_v";
400     
401   // Insert a 'q' before the first '_' character so that it ends up before 
402   // _lane or _n on vector-scalar operations.
403   if (quad) {
404     size_t pos = s.find('_');
405     s = s.insert(pos, "q");
406   }
407   return s;
408 }
409
410 // Generate the string "(argtype a, argtype b, ...)"
411 static std::string GenArgs(const std::string &proto, StringRef typestr) {
412   char arg = 'a';
413   
414   std::string s;
415   s += "(";
416   
417   for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
418     s += TypeString(proto[i], typestr);
419     s.push_back(' ');
420     s.push_back(arg);
421     if ((i + 1) < e)
422       s += ", ";
423   }
424   
425   s += ")";
426   return s;
427 }
428
429 // Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
430 // If structTypes is true, the NEON types are structs of vector types rather
431 // than vector types, and the call becomes "a.val + b.val"
432 static std::string GenOpString(OpKind op, const std::string &proto,
433                                StringRef typestr, bool structTypes = true) {
434   std::string ts = TypeString(proto[0], typestr);
435   std::string s = ts + " r; r";
436
437   bool quad, dummy;
438   char type = ClassifyType(typestr, quad, dummy, dummy);
439   unsigned nElts = 0;
440   switch (type) {
441     case 'c': nElts = 8; break;
442     case 's': nElts = 4; break;
443     case 'i': nElts = 2; break;
444     case 'l': nElts = 1; break;
445     case 'h': nElts = 4; break;
446     case 'f': nElts = 2; break;
447   }
448   nElts <<= quad;
449   
450   if (structTypes)
451     s += ".val";
452   
453   s += " = ";
454
455   std::string a, b, c;
456   if (proto.size() > 1)
457     a = (structTypes && proto[1] != 'l' && proto[1] != 's') ? "a.val" : "a";
458   b = structTypes ? "b.val" : "b";
459   c = structTypes ? "c.val" : "c";
460   
461   switch(op) {
462   case OpAdd:
463     s += a + " + " + b;
464     break;
465   case OpSub:
466     s += a + " - " + b;
467     break;
468   case OpMul:
469     s += a + " * " + b;
470     break;
471   case OpMla:
472     s += a + " + ( " + b + " * " + c + " )";
473     break;
474   case OpMls:
475     s += a + " - ( " + b + " * " + c + " )";
476     break;
477   case OpEq:
478     s += "(__neon_" + ts + ")(" + a + " == " + b + ")";
479     break;
480   case OpGe:
481     s += "(__neon_" + ts + ")(" + a + " >= " + b + ")";
482     break;
483   case OpLe:
484     s += "(__neon_" + ts + ")(" + a + " <= " + b + ")";
485     break;
486   case OpGt:
487     s += "(__neon_" + ts + ")(" + a + " > " + b + ")";
488     break;
489   case OpLt:
490     s += "(__neon_" + ts + ")(" + a + " < " + b + ")";
491     break;
492   case OpNeg:
493     s += " -" + a;
494     break;
495   case OpNot:
496     s += " ~" + a;
497     break;
498   case OpAnd:
499     s += a + " & " + b;
500     break;
501   case OpOr:
502     s += a + " | " + b;
503     break;
504   case OpXor:
505     s += a + " ^ " + b;
506     break;
507   case OpAndNot:
508     s += a + " & ~" + b;
509     break;
510   case OpOrNot:
511     s += a + " | ~" + b;
512     break;
513   case OpCast:
514     s += "(__neon_" + ts + ")" + a;
515     break;
516   case OpConcat:
517     s += "__builtin_shufflevector((__neon_int64x1_t)" + a;
518     s += ", (__neon_int64x1_t)" + b + ", 0, 1)";
519     break;
520   case OpDup:
521     s += "(__neon_" + ts + "){ ";
522     for (unsigned i = 0; i != nElts; ++i) {
523       s += a;
524       if ((i + 1) < nElts)
525         s += ", ";
526     }
527     s += " }";
528     break;
529   default:
530     throw "unknown OpKind!";
531     break;
532   }
533   s += "; return r;";
534   return s;
535 }
536
537 static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
538   unsigned mod = proto[0];
539   unsigned ret = 0;
540
541   if (mod == 'v' || mod == 'f')
542     mod = proto[1];
543
544   bool quad = false;
545   bool poly = false;
546   bool usgn = false;
547   bool scal = false;
548   bool cnst = false;
549   bool pntr = false;
550   
551   // base type to get the type string for.
552   char type = ClassifyType(typestr, quad, poly, usgn);
553   
554   // Based on the modifying character, change the type and width if necessary.
555   type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
556   
557   if (usgn)
558     ret |= 0x08;
559   if (quad)
560     ret |= 0x10;
561   
562   switch (type) {
563     case 'c': 
564       ret |= poly ? 5 : 0;
565       break;
566     case 's':
567       ret |= poly ? 6 : 1;
568       break;
569     case 'i':
570       ret |= 2;
571       break;
572     case 'l':
573       ret |= 3;
574       break;
575     case 'h':
576       ret |= 7;
577       break;
578     case 'f':
579       ret |= 4;
580       break;
581     default:
582       throw "unhandled type!";
583       break;
584   }
585   return ret;
586 }
587
588 // Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
589 // If structTypes is true, the NEON types are structs of vector types rather
590 // than vector types, and the call becomes __builtin_neon_cls(a.val)
591 static std::string GenBuiltin(const std::string &name, const std::string &proto,
592                               StringRef typestr, ClassKind ck,
593                               bool structTypes = true) {
594   char arg = 'a';
595   std::string s;
596
597   bool unioning = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4');
598
599   // If all types are the same size, bitcasting the args will take care 
600   // of arg checking.  The actual signedness etc. will be taken care of with
601   // special enums.
602   if (proto.find('s') == std::string::npos)
603     ck = ClassB;
604
605   if (proto[0] != 'v') {
606     if (unioning) {
607       s += "union { ";
608       s += TypeString(proto[0], typestr, true) + " val; ";
609       s += TypeString(proto[0], typestr, false) + " s; ";
610       s += "} r;";
611     } else {
612       s += TypeString(proto[0], typestr);
613     }
614     
615     s += " r; r";
616     if (structTypes && proto[0] != 's' && proto[0] != 'i' && proto[0] != 'l')
617       s += ".val";
618     
619     s += " = ";
620   }    
621   
622   s += "__builtin_neon_";
623   s += MangleName(name, typestr, ck);
624   s += "(";
625   
626   for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
627     // Handle multiple-vector values specially, emitting each subvector as an
628     // argument to the __builtin.
629     if (structTypes && (proto[i] == '2' || proto[i] == '3' || proto[i] == '4')){
630       for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
631         s.push_back(arg);
632         s += ".val[" + utostr(vi) + "]";
633         if ((vi + 1) < ve)
634           s += ", ";
635       }
636       if ((i + 1) < e)
637         s += ", ";
638
639       continue;
640     }
641     
642     s.push_back(arg);
643     
644     if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' &&
645         proto[i] != 'p' && proto[i] != 'c') {
646       s += ".val";
647     }
648     if ((i + 1) < e)
649       s += ", ";
650   }
651   
652   // Extra constant integer to hold type class enum for this function, e.g. s8
653   if (ck == ClassB)
654     s += ", " + utostr(GetNeonEnum(proto, typestr));
655   
656   s += ");";
657
658   if (proto[0] != 'v') {
659     if (unioning)
660       s += " return r.s;";
661     else
662       s += " return r;";
663   }
664   return s;
665 }
666
667 static std::string GenBuiltinDef(const std::string &name, 
668                                  const std::string &proto,
669                                  StringRef typestr, ClassKind ck) {
670   std::string s("BUILTIN(__builtin_neon_");
671
672   // If all types are the same size, bitcasting the args will take care 
673   // of arg checking.  The actual signedness etc. will be taken care of with
674   // special enums.
675   if (proto.find('s') == std::string::npos)
676     ck = ClassB;
677   
678   s += MangleName(name, typestr, ck);
679   s += ", \"";
680   
681   for (unsigned i = 0, e = proto.size(); i != e; ++i)
682     s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
683
684   // Extra constant integer to hold type class enum for this function, e.g. s8
685   if (ck == ClassB)
686     s += "i";
687   
688   s += "\", \"n\")";
689   return s;
690 }
691
692 void NeonEmitter::run(raw_ostream &OS) {
693   EmitSourceFileHeader("ARM NEON Header", OS);
694   
695   // FIXME: emit license into file?
696   
697   OS << "#ifndef __ARM_NEON_H\n";
698   OS << "#define __ARM_NEON_H\n\n";
699   
700   OS << "#ifndef __ARM_NEON__\n";
701   OS << "#error \"NEON support not enabled\"\n";
702   OS << "#endif\n\n";
703
704   OS << "#include <stdint.h>\n\n";
705
706   // Emit NEON-specific scalar typedefs.
707   // FIXME: probably need to do something better for polynomial types.
708   // FIXME: is this the correct thing to do for float16?
709   OS << "typedef float float32_t;\n";
710   OS << "typedef uint8_t poly8_t;\n";
711   OS << "typedef uint16_t poly16_t;\n";
712   OS << "typedef uint16_t float16_t;\n";
713
714   // Emit Neon vector typedefs.
715   std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
716   SmallVector<StringRef, 24> TDTypeVec;
717   ParseTypes(0, TypedefTypes, TDTypeVec);
718
719   // Emit vector typedefs.
720   for (unsigned v = 1; v != 5; ++v) {
721     for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
722       bool dummy, quad = false;
723       (void) ClassifyType(TDTypeVec[i], quad, dummy, dummy);
724       OS << "typedef __attribute__(( __vector_size__(";
725       
726       OS << utostr(8*v*(quad ? 2 : 1)) << ") )) ";
727       if (!quad)
728         OS << " ";
729       
730       OS << TypeString('s', TDTypeVec[i]);
731       OS << " __neon_";
732       
733       char t = (v == 1) ? 'd' : '0' + v;
734       OS << TypeString(t, TDTypeVec[i]) << ";\n";
735     }
736   }
737   OS << "\n";
738
739   // Emit struct typedefs.
740   for (unsigned vi = 1; vi != 5; ++vi) {
741     for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
742       std::string ts = TypeString('d', TDTypeVec[i]);
743       std::string vs = (vi > 1) ? TypeString('0' + vi, TDTypeVec[i]) : ts;
744       OS << "typedef struct __" << vs << " {\n";
745       OS << "  __neon_" << ts << " val";
746       if (vi > 1)
747         OS << "[" << utostr(vi) << "]";
748       OS << ";\n} " << vs << ";\n\n";
749     }
750   }
751   
752   OS << "#define __ai static __attribute__((__always_inline__))\n\n";
753
754   std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
755   
756   // Unique the return+pattern types, and assign them.
757   for (unsigned i = 0, e = RV.size(); i != e; ++i) {
758     Record *R = RV[i];
759     std::string name = LowercaseString(R->getName());
760     std::string Proto = R->getValueAsString("Prototype");
761     std::string Types = R->getValueAsString("Types");
762     
763     SmallVector<StringRef, 16> TypeVec;
764     ParseTypes(R, Types, TypeVec);
765     
766     OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
767     
768     for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
769       assert(!Proto.empty() && "");
770       
771       // static always inline + return type
772       OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
773       
774       // Function name with type suffix
775       OS << " " << MangleName(name, TypeVec[ti], ClassS);
776       
777       // Function arguments
778       OS << GenArgs(Proto, TypeVec[ti]);
779       
780       // Definition.
781       OS << " { ";
782       
783       if (k != OpNone) {
784         OS << GenOpString(k, Proto, TypeVec[ti]);
785       } else {
786         if (R->getSuperClasses().size() < 2)
787           throw TGError(R->getLoc(), "Builtin has no class kind");
788         
789         ClassKind ck = ClassMap[R->getSuperClasses()[1]];
790
791         if (ck == ClassNone)
792           throw TGError(R->getLoc(), "Builtin has no class kind");
793         OS << GenBuiltin(name, Proto, TypeVec[ti], ck);
794       }
795
796       OS << " }\n";
797     }
798     OS << "\n";
799   }
800   OS << "#undef __ai\n\n";
801   OS << "#endif /* __ARM_NEON_H */\n";
802 }
803
804 void NeonEmitter::runHeader(raw_ostream &OS) {
805   std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
806
807   StringMap<OpKind> EmittedMap;
808   
809   for (unsigned i = 0, e = RV.size(); i != e; ++i) {
810     Record *R = RV[i];
811
812     OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
813     if (k != OpNone)
814       continue;
815     
816     std::string name = LowercaseString(R->getName());
817     std::string Proto = R->getValueAsString("Prototype");
818     std::string Types = R->getValueAsString("Types");
819
820     SmallVector<StringRef, 16> TypeVec;
821     ParseTypes(R, Types, TypeVec);
822
823     if (R->getSuperClasses().size() < 2)
824       throw TGError(R->getLoc(), "Builtin has no class kind");
825     
826     ClassKind ck = ClassMap[R->getSuperClasses()[1]];
827     
828     for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
829       std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
830       if (EmittedMap.count(bd))
831         continue;
832       
833       EmittedMap[bd] = OpNone;
834       OS << bd << "\n";
835     }
836   }
837 }