LLVM 18.0.0git
FunctionComparator.cpp
Go to the documentation of this file.
1//===- FunctionComparator.h - Function Comparator -------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the FunctionComparator and GlobalNumberState classes
10// which are used by the MergeFunctions pass for comparing functions.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/APFloat.h"
16#include "llvm/ADT/APInt.h"
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/Hashing.h"
21#include "llvm/IR/Attributes.h"
22#include "llvm/IR/BasicBlock.h"
23#include "llvm/IR/Constant.h"
24#include "llvm/IR/Constants.h"
25#include "llvm/IR/DataLayout.h"
27#include "llvm/IR/Function.h"
28#include "llvm/IR/GlobalValue.h"
29#include "llvm/IR/InlineAsm.h"
30#include "llvm/IR/InstrTypes.h"
31#include "llvm/IR/Instruction.h"
33#include "llvm/IR/LLVMContext.h"
34#include "llvm/IR/Metadata.h"
35#include "llvm/IR/Module.h"
36#include "llvm/IR/Operator.h"
37#include "llvm/IR/Type.h"
38#include "llvm/IR/Value.h"
41#include "llvm/Support/Debug.h"
44#include <cassert>
45#include <cstddef>
46#include <cstdint>
47#include <utility>
48
49using namespace llvm;
50
51#define DEBUG_TYPE "functioncomparator"
52
54 if (L < R)
55 return -1;
56 if (L > R)
57 return 1;
58 return 0;
59}
60
62 if (L.value() < R.value())
63 return -1;
64 if (L.value() > R.value())
65 return 1;
66 return 0;
67}
68
69int FunctionComparator::cmpOrderings(AtomicOrdering L, AtomicOrdering R) const {
70 if ((int)L < (int)R)
71 return -1;
72 if ((int)L > (int)R)
73 return 1;
74 return 0;
75}
76
77int FunctionComparator::cmpAPInts(const APInt &L, const APInt &R) const {
78 if (int Res = cmpNumbers(L.getBitWidth(), R.getBitWidth()))
79 return Res;
80 if (L.ugt(R))
81 return 1;
82 if (R.ugt(L))
83 return -1;
84 return 0;
85}
86
87int FunctionComparator::cmpAPFloats(const APFloat &L, const APFloat &R) const {
88 // Floats are ordered first by semantics (i.e. float, double, half, etc.),
89 // then by value interpreted as a bitstring (aka APInt).
90 const fltSemantics &SL = L.getSemantics(), &SR = R.getSemantics();
93 return Res;
96 return Res;
99 return Res;
102 return Res;
103 return cmpAPInts(L.bitcastToAPInt(), R.bitcastToAPInt());
104}
105
107 // Prevent heavy comparison, compare sizes first.
108 if (int Res = cmpNumbers(L.size(), R.size()))
109 return Res;
110
111 // Compare strings lexicographically only when it is necessary: only when
112 // strings are equal in size.
113 return std::clamp(L.compare(R), -1, 1);
114}
115
116int FunctionComparator::cmpAttrs(const AttributeList L,
117 const AttributeList R) const {
118 if (int Res = cmpNumbers(L.getNumAttrSets(), R.getNumAttrSets()))
119 return Res;
120
121 for (unsigned i : L.indexes()) {
122 AttributeSet LAS = L.getAttributes(i);
123 AttributeSet RAS = R.getAttributes(i);
124 AttributeSet::iterator LI = LAS.begin(), LE = LAS.end();
125 AttributeSet::iterator RI = RAS.begin(), RE = RAS.end();
126 for (; LI != LE && RI != RE; ++LI, ++RI) {
127 Attribute LA = *LI;
128 Attribute RA = *RI;
129 if (LA.isTypeAttribute() && RA.isTypeAttribute()) {
130 if (LA.getKindAsEnum() != RA.getKindAsEnum())
131 return cmpNumbers(LA.getKindAsEnum(), RA.getKindAsEnum());
132
133 Type *TyL = LA.getValueAsType();
134 Type *TyR = RA.getValueAsType();
135 if (TyL && TyR) {
136 if (int Res = cmpTypes(TyL, TyR))
137 return Res;
138 continue;
139 }
140
141 // Two pointers, at least one null, so the comparison result is
142 // independent of the value of a real pointer.
143 if (int Res = cmpNumbers((uint64_t)TyL, (uint64_t)TyR))
144 return Res;
145 continue;
146 }
147 if (LA < RA)
148 return -1;
149 if (RA < LA)
150 return 1;
151 }
152 if (LI != LE)
153 return 1;
154 if (RI != RE)
155 return -1;
156 }
157 return 0;
158}
159
160int FunctionComparator::cmpMetadata(const Metadata *L,
161 const Metadata *R) const {
162 // TODO: the following routine coerce the metadata contents into constants
163 // before comparison.
164 // It ignores any other cases, so that the metadata nodes are considered
165 // equal even though this is not correct.
166 // We should structurally compare the metadata nodes to be perfect here.
167 auto *CL = dyn_cast<ConstantAsMetadata>(L);
168 auto *CR = dyn_cast<ConstantAsMetadata>(R);
169 if (CL == CR)
170 return 0;
171 if (!CL)
172 return -1;
173 if (!CR)
174 return 1;
175 return cmpConstants(CL->getValue(), CR->getValue());
176}
177
178int FunctionComparator::cmpMDNode(const MDNode *L, const MDNode *R) const {
179 if (L == R)
180 return 0;
181 if (!L)
182 return -1;
183 if (!R)
184 return 1;
185 // TODO: Note that as this is metadata, it is possible to drop and/or merge
186 // this data when considering functions to merge. Thus this comparison would
187 // return 0 (i.e. equivalent), but merging would become more complicated
188 // because the ranges would need to be unioned. It is not likely that
189 // functions differ ONLY in this metadata if they are actually the same
190 // function semantically.
191 if (int Res = cmpNumbers(L->getNumOperands(), R->getNumOperands()))
192 return Res;
193 for (size_t I = 0; I < L->getNumOperands(); ++I)
194 if (int Res = cmpMetadata(L->getOperand(I), R->getOperand(I)))
195 return Res;
196 return 0;
197}
198
199int FunctionComparator::cmpInstMetadata(Instruction const *L,
200 Instruction const *R) const {
201 /// These metadata affects the other optimization passes by making assertions
202 /// or constraints.
203 /// Values that carry different expectations should be considered different.
205 L->getAllMetadataOtherThanDebugLoc(MDL);
206 R->getAllMetadataOtherThanDebugLoc(MDR);
207 if (MDL.size() > MDR.size())
208 return 1;
209 else if (MDL.size() < MDR.size())
210 return -1;
211 for (size_t I = 0, N = MDL.size(); I < N; ++I) {
212 auto const [KeyL, ML] = MDL[I];
213 auto const [KeyR, MR] = MDR[I];
214 if (int Res = cmpNumbers(KeyL, KeyR))
215 return Res;
216 if (int Res = cmpMDNode(ML, MR))
217 return Res;
218 }
219 return 0;
220}
221
222int FunctionComparator::cmpOperandBundlesSchema(const CallBase &LCS,
223 const CallBase &RCS) const {
224 assert(LCS.getOpcode() == RCS.getOpcode() && "Can't compare otherwise!");
225
226 if (int Res =
228 return Res;
229
230 for (unsigned I = 0, E = LCS.getNumOperandBundles(); I != E; ++I) {
231 auto OBL = LCS.getOperandBundleAt(I);
232 auto OBR = RCS.getOperandBundleAt(I);
233
234 if (int Res = OBL.getTagName().compare(OBR.getTagName()))
235 return Res;
236
237 if (int Res = cmpNumbers(OBL.Inputs.size(), OBR.Inputs.size()))
238 return Res;
239 }
240
241 return 0;
242}
243
244/// Constants comparison:
245/// 1. Check whether type of L constant could be losslessly bitcasted to R
246/// type.
247/// 2. Compare constant contents.
248/// For more details see declaration comments.
250 const Constant *R) const {
251 Type *TyL = L->getType();
252 Type *TyR = R->getType();
253
254 // Check whether types are bitcastable. This part is just re-factored
255 // Type::canLosslesslyBitCastTo method, but instead of returning true/false,
256 // we also pack into result which type is "less" for us.
257 int TypesRes = cmpTypes(TyL, TyR);
258 if (TypesRes != 0) {
259 // Types are different, but check whether we can bitcast them.
260 if (!TyL->isFirstClassType()) {
261 if (TyR->isFirstClassType())
262 return -1;
263 // Neither TyL nor TyR are values of first class type. Return the result
264 // of comparing the types
265 return TypesRes;
266 }
267 if (!TyR->isFirstClassType()) {
268 if (TyL->isFirstClassType())
269 return 1;
270 return TypesRes;
271 }
272
273 // Vector -> Vector conversions are always lossless if the two vector types
274 // have the same size, otherwise not.
275 unsigned TyLWidth = 0;
276 unsigned TyRWidth = 0;
277
278 if (auto *VecTyL = dyn_cast<VectorType>(TyL))
279 TyLWidth = VecTyL->getPrimitiveSizeInBits().getFixedValue();
280 if (auto *VecTyR = dyn_cast<VectorType>(TyR))
281 TyRWidth = VecTyR->getPrimitiveSizeInBits().getFixedValue();
282
283 if (TyLWidth != TyRWidth)
284 return cmpNumbers(TyLWidth, TyRWidth);
285
286 // Zero bit-width means neither TyL nor TyR are vectors.
287 if (!TyLWidth) {
288 PointerType *PTyL = dyn_cast<PointerType>(TyL);
289 PointerType *PTyR = dyn_cast<PointerType>(TyR);
290 if (PTyL && PTyR) {
291 unsigned AddrSpaceL = PTyL->getAddressSpace();
292 unsigned AddrSpaceR = PTyR->getAddressSpace();
293 if (int Res = cmpNumbers(AddrSpaceL, AddrSpaceR))
294 return Res;
295 }
296 if (PTyL)
297 return 1;
298 if (PTyR)
299 return -1;
300
301 // TyL and TyR aren't vectors, nor pointers. We don't know how to
302 // bitcast them.
303 return TypesRes;
304 }
305 }
306
307 // OK, types are bitcastable, now check constant contents.
308
309 if (L->isNullValue() && R->isNullValue())
310 return TypesRes;
311 if (L->isNullValue() && !R->isNullValue())
312 return 1;
313 if (!L->isNullValue() && R->isNullValue())
314 return -1;
315
316 auto GlobalValueL = const_cast<GlobalValue *>(dyn_cast<GlobalValue>(L));
317 auto GlobalValueR = const_cast<GlobalValue *>(dyn_cast<GlobalValue>(R));
318 if (GlobalValueL && GlobalValueR) {
319 return cmpGlobalValues(GlobalValueL, GlobalValueR);
320 }
321
322 if (int Res = cmpNumbers(L->getValueID(), R->getValueID()))
323 return Res;
324
325 if (const auto *SeqL = dyn_cast<ConstantDataSequential>(L)) {
326 const auto *SeqR = cast<ConstantDataSequential>(R);
327 // This handles ConstantDataArray and ConstantDataVector. Note that we
328 // compare the two raw data arrays, which might differ depending on the host
329 // endianness. This isn't a problem though, because the endiness of a module
330 // will affect the order of the constants, but this order is the same
331 // for a given input module and host platform.
332 return cmpMem(SeqL->getRawDataValues(), SeqR->getRawDataValues());
333 }
334
335 switch (L->getValueID()) {
336 case Value::UndefValueVal:
337 case Value::PoisonValueVal:
338 case Value::ConstantTokenNoneVal:
339 return TypesRes;
340 case Value::ConstantIntVal: {
341 const APInt &LInt = cast<ConstantInt>(L)->getValue();
342 const APInt &RInt = cast<ConstantInt>(R)->getValue();
343 return cmpAPInts(LInt, RInt);
344 }
345 case Value::ConstantFPVal: {
346 const APFloat &LAPF = cast<ConstantFP>(L)->getValueAPF();
347 const APFloat &RAPF = cast<ConstantFP>(R)->getValueAPF();
348 return cmpAPFloats(LAPF, RAPF);
349 }
350 case Value::ConstantArrayVal: {
351 const ConstantArray *LA = cast<ConstantArray>(L);
352 const ConstantArray *RA = cast<ConstantArray>(R);
353 uint64_t NumElementsL = cast<ArrayType>(TyL)->getNumElements();
354 uint64_t NumElementsR = cast<ArrayType>(TyR)->getNumElements();
355 if (int Res = cmpNumbers(NumElementsL, NumElementsR))
356 return Res;
357 for (uint64_t i = 0; i < NumElementsL; ++i) {
358 if (int Res = cmpConstants(cast<Constant>(LA->getOperand(i)),
359 cast<Constant>(RA->getOperand(i))))
360 return Res;
361 }
362 return 0;
363 }
364 case Value::ConstantStructVal: {
365 const ConstantStruct *LS = cast<ConstantStruct>(L);
366 const ConstantStruct *RS = cast<ConstantStruct>(R);
367 unsigned NumElementsL = cast<StructType>(TyL)->getNumElements();
368 unsigned NumElementsR = cast<StructType>(TyR)->getNumElements();
369 if (int Res = cmpNumbers(NumElementsL, NumElementsR))
370 return Res;
371 for (unsigned i = 0; i != NumElementsL; ++i) {
372 if (int Res = cmpConstants(cast<Constant>(LS->getOperand(i)),
373 cast<Constant>(RS->getOperand(i))))
374 return Res;
375 }
376 return 0;
377 }
378 case Value::ConstantVectorVal: {
379 const ConstantVector *LV = cast<ConstantVector>(L);
380 const ConstantVector *RV = cast<ConstantVector>(R);
381 unsigned NumElementsL = cast<FixedVectorType>(TyL)->getNumElements();
382 unsigned NumElementsR = cast<FixedVectorType>(TyR)->getNumElements();
383 if (int Res = cmpNumbers(NumElementsL, NumElementsR))
384 return Res;
385 for (uint64_t i = 0; i < NumElementsL; ++i) {
386 if (int Res = cmpConstants(cast<Constant>(LV->getOperand(i)),
387 cast<Constant>(RV->getOperand(i))))
388 return Res;
389 }
390 return 0;
391 }
392 case Value::ConstantExprVal: {
393 const ConstantExpr *LE = cast<ConstantExpr>(L);
394 const ConstantExpr *RE = cast<ConstantExpr>(R);
395 unsigned NumOperandsL = LE->getNumOperands();
396 unsigned NumOperandsR = RE->getNumOperands();
397 if (int Res = cmpNumbers(NumOperandsL, NumOperandsR))
398 return Res;
399 for (unsigned i = 0; i < NumOperandsL; ++i) {
400 if (int Res = cmpConstants(cast<Constant>(LE->getOperand(i)),
401 cast<Constant>(RE->getOperand(i))))
402 return Res;
403 }
404 return 0;
405 }
406 case Value::BlockAddressVal: {
407 const BlockAddress *LBA = cast<BlockAddress>(L);
408 const BlockAddress *RBA = cast<BlockAddress>(R);
409 if (int Res = cmpValues(LBA->getFunction(), RBA->getFunction()))
410 return Res;
411 if (LBA->getFunction() == RBA->getFunction()) {
412 // They are BBs in the same function. Order by which comes first in the
413 // BB order of the function. This order is deterministic.
414 Function *F = LBA->getFunction();
415 BasicBlock *LBB = LBA->getBasicBlock();
416 BasicBlock *RBB = RBA->getBasicBlock();
417 if (LBB == RBB)
418 return 0;
419 for (BasicBlock &BB : *F) {
420 if (&BB == LBB) {
421 assert(&BB != RBB);
422 return -1;
423 }
424 if (&BB == RBB)
425 return 1;
426 }
427 llvm_unreachable("Basic Block Address does not point to a basic block in "
428 "its function.");
429 return -1;
430 } else {
431 // cmpValues said the functions are the same. So because they aren't
432 // literally the same pointer, they must respectively be the left and
433 // right functions.
434 assert(LBA->getFunction() == FnL && RBA->getFunction() == FnR);
435 // cmpValues will tell us if these are equivalent BasicBlocks, in the
436 // context of their respective functions.
437 return cmpValues(LBA->getBasicBlock(), RBA->getBasicBlock());
438 }
439 }
440 case Value::DSOLocalEquivalentVal: {
441 // dso_local_equivalent is functionally equivalent to whatever it points to.
442 // This means the behavior of the IR should be the exact same as if the
443 // function was referenced directly rather than through a
444 // dso_local_equivalent.
445 const auto *LEquiv = cast<DSOLocalEquivalent>(L);
446 const auto *REquiv = cast<DSOLocalEquivalent>(R);
447 return cmpGlobalValues(LEquiv->getGlobalValue(), REquiv->getGlobalValue());
448 }
449 default: // Unknown constant, abort.
450 LLVM_DEBUG(dbgs() << "Looking at valueID " << L->getValueID() << "\n");
451 llvm_unreachable("Constant ValueID not recognized.");
452 return -1;
453 }
454}
455
457 uint64_t LNumber = GlobalNumbers->getNumber(L);
458 uint64_t RNumber = GlobalNumbers->getNumber(R);
459 return cmpNumbers(LNumber, RNumber);
460}
461
462/// cmpType - compares two types,
463/// defines total ordering among the types set.
464/// See method declaration comments for more details.
466 PointerType *PTyL = dyn_cast<PointerType>(TyL);
467 PointerType *PTyR = dyn_cast<PointerType>(TyR);
468
469 const DataLayout &DL = FnL->getParent()->getDataLayout();
470 if (PTyL && PTyL->getAddressSpace() == 0)
471 TyL = DL.getIntPtrType(TyL);
472 if (PTyR && PTyR->getAddressSpace() == 0)
473 TyR = DL.getIntPtrType(TyR);
474
475 if (TyL == TyR)
476 return 0;
477
478 if (int Res = cmpNumbers(TyL->getTypeID(), TyR->getTypeID()))
479 return Res;
480
481 switch (TyL->getTypeID()) {
482 default:
483 llvm_unreachable("Unknown type!");
485 return cmpNumbers(cast<IntegerType>(TyL)->getBitWidth(),
486 cast<IntegerType>(TyR)->getBitWidth());
487 // TyL == TyR would have returned true earlier, because types are uniqued.
488 case Type::VoidTyID:
489 case Type::FloatTyID:
490 case Type::DoubleTyID:
492 case Type::FP128TyID:
494 case Type::LabelTyID:
496 case Type::TokenTyID:
497 return 0;
498
500 assert(PTyL && PTyR && "Both types must be pointers here.");
501 return cmpNumbers(PTyL->getAddressSpace(), PTyR->getAddressSpace());
502
503 case Type::StructTyID: {
504 StructType *STyL = cast<StructType>(TyL);
505 StructType *STyR = cast<StructType>(TyR);
506 if (STyL->getNumElements() != STyR->getNumElements())
507 return cmpNumbers(STyL->getNumElements(), STyR->getNumElements());
508
509 if (STyL->isPacked() != STyR->isPacked())
510 return cmpNumbers(STyL->isPacked(), STyR->isPacked());
511
512 for (unsigned i = 0, e = STyL->getNumElements(); i != e; ++i) {
513 if (int Res = cmpTypes(STyL->getElementType(i), STyR->getElementType(i)))
514 return Res;
515 }
516 return 0;
517 }
518
519 case Type::FunctionTyID: {
520 FunctionType *FTyL = cast<FunctionType>(TyL);
521 FunctionType *FTyR = cast<FunctionType>(TyR);
522 if (FTyL->getNumParams() != FTyR->getNumParams())
523 return cmpNumbers(FTyL->getNumParams(), FTyR->getNumParams());
524
525 if (FTyL->isVarArg() != FTyR->isVarArg())
526 return cmpNumbers(FTyL->isVarArg(), FTyR->isVarArg());
527
528 if (int Res = cmpTypes(FTyL->getReturnType(), FTyR->getReturnType()))
529 return Res;
530
531 for (unsigned i = 0, e = FTyL->getNumParams(); i != e; ++i) {
532 if (int Res = cmpTypes(FTyL->getParamType(i), FTyR->getParamType(i)))
533 return Res;
534 }
535 return 0;
536 }
537
538 case Type::ArrayTyID: {
539 auto *STyL = cast<ArrayType>(TyL);
540 auto *STyR = cast<ArrayType>(TyR);
541 if (STyL->getNumElements() != STyR->getNumElements())
542 return cmpNumbers(STyL->getNumElements(), STyR->getNumElements());
543 return cmpTypes(STyL->getElementType(), STyR->getElementType());
544 }
547 auto *STyL = cast<VectorType>(TyL);
548 auto *STyR = cast<VectorType>(TyR);
549 if (STyL->getElementCount().isScalable() !=
550 STyR->getElementCount().isScalable())
551 return cmpNumbers(STyL->getElementCount().isScalable(),
552 STyR->getElementCount().isScalable());
553 if (STyL->getElementCount() != STyR->getElementCount())
554 return cmpNumbers(STyL->getElementCount().getKnownMinValue(),
555 STyR->getElementCount().getKnownMinValue());
556 return cmpTypes(STyL->getElementType(), STyR->getElementType());
557 }
558 }
559}
560
561// Determine whether the two operations are the same except that pointer-to-A
562// and pointer-to-B are equivalent. This should be kept in sync with
563// Instruction::isSameOperationAs.
564// Read method declaration comments for more details.
566 const Instruction *R,
567 bool &needToCmpOperands) const {
568 needToCmpOperands = true;
569 if (int Res = cmpValues(L, R))
570 return Res;
571
572 // Differences from Instruction::isSameOperationAs:
573 // * replace type comparison with calls to cmpTypes.
574 // * we test for I->getRawSubclassOptionalData (nuw/nsw/tail) at the top.
575 // * because of the above, we don't test for the tail bit on calls later on.
576 if (int Res = cmpNumbers(L->getOpcode(), R->getOpcode()))
577 return Res;
578
579 if (const GetElementPtrInst *GEPL = dyn_cast<GetElementPtrInst>(L)) {
580 needToCmpOperands = false;
581 const GetElementPtrInst *GEPR = cast<GetElementPtrInst>(R);
582 if (int Res =
583 cmpValues(GEPL->getPointerOperand(), GEPR->getPointerOperand()))
584 return Res;
585 return cmpGEPs(GEPL, GEPR);
586 }
587
588 if (int Res = cmpNumbers(L->getNumOperands(), R->getNumOperands()))
589 return Res;
590
591 if (int Res = cmpTypes(L->getType(), R->getType()))
592 return Res;
593
594 if (int Res = cmpNumbers(L->getRawSubclassOptionalData(),
595 R->getRawSubclassOptionalData()))
596 return Res;
597
598 // We have two instructions of identical opcode and #operands. Check to see
599 // if all operands are the same type
600 for (unsigned i = 0, e = L->getNumOperands(); i != e; ++i) {
601 if (int Res =
602 cmpTypes(L->getOperand(i)->getType(), R->getOperand(i)->getType()))
603 return Res;
604 }
605
606 // Check special state that is a part of some instructions.
607 if (const AllocaInst *AI = dyn_cast<AllocaInst>(L)) {
608 if (int Res = cmpTypes(AI->getAllocatedType(),
609 cast<AllocaInst>(R)->getAllocatedType()))
610 return Res;
611 return cmpAligns(AI->getAlign(), cast<AllocaInst>(R)->getAlign());
612 }
613 if (const LoadInst *LI = dyn_cast<LoadInst>(L)) {
614 if (int Res = cmpNumbers(LI->isVolatile(), cast<LoadInst>(R)->isVolatile()))
615 return Res;
616 if (int Res = cmpAligns(LI->getAlign(), cast<LoadInst>(R)->getAlign()))
617 return Res;
618 if (int Res =
619 cmpOrderings(LI->getOrdering(), cast<LoadInst>(R)->getOrdering()))
620 return Res;
621 if (int Res = cmpNumbers(LI->getSyncScopeID(),
622 cast<LoadInst>(R)->getSyncScopeID()))
623 return Res;
624 return cmpInstMetadata(L, R);
625 }
626 if (const StoreInst *SI = dyn_cast<StoreInst>(L)) {
627 if (int Res =
628 cmpNumbers(SI->isVolatile(), cast<StoreInst>(R)->isVolatile()))
629 return Res;
630 if (int Res = cmpAligns(SI->getAlign(), cast<StoreInst>(R)->getAlign()))
631 return Res;
632 if (int Res =
633 cmpOrderings(SI->getOrdering(), cast<StoreInst>(R)->getOrdering()))
634 return Res;
635 return cmpNumbers(SI->getSyncScopeID(),
636 cast<StoreInst>(R)->getSyncScopeID());
637 }
638 if (const CmpInst *CI = dyn_cast<CmpInst>(L))
639 return cmpNumbers(CI->getPredicate(), cast<CmpInst>(R)->getPredicate());
640 if (auto *CBL = dyn_cast<CallBase>(L)) {
641 auto *CBR = cast<CallBase>(R);
642 if (int Res = cmpNumbers(CBL->getCallingConv(), CBR->getCallingConv()))
643 return Res;
644 if (int Res = cmpAttrs(CBL->getAttributes(), CBR->getAttributes()))
645 return Res;
646 if (int Res = cmpOperandBundlesSchema(*CBL, *CBR))
647 return Res;
648 if (const CallInst *CI = dyn_cast<CallInst>(L))
649 if (int Res = cmpNumbers(CI->getTailCallKind(),
650 cast<CallInst>(R)->getTailCallKind()))
651 return Res;
652 return cmpMDNode(L->getMetadata(LLVMContext::MD_range),
653 R->getMetadata(LLVMContext::MD_range));
654 }
655 if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(L)) {
656 ArrayRef<unsigned> LIndices = IVI->getIndices();
657 ArrayRef<unsigned> RIndices = cast<InsertValueInst>(R)->getIndices();
658 if (int Res = cmpNumbers(LIndices.size(), RIndices.size()))
659 return Res;
660 for (size_t i = 0, e = LIndices.size(); i != e; ++i) {
661 if (int Res = cmpNumbers(LIndices[i], RIndices[i]))
662 return Res;
663 }
664 return 0;
665 }
666 if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(L)) {
667 ArrayRef<unsigned> LIndices = EVI->getIndices();
668 ArrayRef<unsigned> RIndices = cast<ExtractValueInst>(R)->getIndices();
669 if (int Res = cmpNumbers(LIndices.size(), RIndices.size()))
670 return Res;
671 for (size_t i = 0, e = LIndices.size(); i != e; ++i) {
672 if (int Res = cmpNumbers(LIndices[i], RIndices[i]))
673 return Res;
674 }
675 }
676 if (const FenceInst *FI = dyn_cast<FenceInst>(L)) {
677 if (int Res =
678 cmpOrderings(FI->getOrdering(), cast<FenceInst>(R)->getOrdering()))
679 return Res;
680 return cmpNumbers(FI->getSyncScopeID(),
681 cast<FenceInst>(R)->getSyncScopeID());
682 }
683 if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(L)) {
684 if (int Res = cmpNumbers(CXI->isVolatile(),
685 cast<AtomicCmpXchgInst>(R)->isVolatile()))
686 return Res;
687 if (int Res =
688 cmpNumbers(CXI->isWeak(), cast<AtomicCmpXchgInst>(R)->isWeak()))
689 return Res;
690 if (int Res =
691 cmpOrderings(CXI->getSuccessOrdering(),
692 cast<AtomicCmpXchgInst>(R)->getSuccessOrdering()))
693 return Res;
694 if (int Res =
695 cmpOrderings(CXI->getFailureOrdering(),
696 cast<AtomicCmpXchgInst>(R)->getFailureOrdering()))
697 return Res;
698 return cmpNumbers(CXI->getSyncScopeID(),
699 cast<AtomicCmpXchgInst>(R)->getSyncScopeID());
700 }
701 if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(L)) {
702 if (int Res = cmpNumbers(RMWI->getOperation(),
703 cast<AtomicRMWInst>(R)->getOperation()))
704 return Res;
705 if (int Res = cmpNumbers(RMWI->isVolatile(),
706 cast<AtomicRMWInst>(R)->isVolatile()))
707 return Res;
708 if (int Res = cmpOrderings(RMWI->getOrdering(),
709 cast<AtomicRMWInst>(R)->getOrdering()))
710 return Res;
711 return cmpNumbers(RMWI->getSyncScopeID(),
712 cast<AtomicRMWInst>(R)->getSyncScopeID());
713 }
714 if (const ShuffleVectorInst *SVI = dyn_cast<ShuffleVectorInst>(L)) {
715 ArrayRef<int> LMask = SVI->getShuffleMask();
716 ArrayRef<int> RMask = cast<ShuffleVectorInst>(R)->getShuffleMask();
717 if (int Res = cmpNumbers(LMask.size(), RMask.size()))
718 return Res;
719 for (size_t i = 0, e = LMask.size(); i != e; ++i) {
720 if (int Res = cmpNumbers(LMask[i], RMask[i]))
721 return Res;
722 }
723 }
724 if (const PHINode *PNL = dyn_cast<PHINode>(L)) {
725 const PHINode *PNR = cast<PHINode>(R);
726 // Ensure that in addition to the incoming values being identical
727 // (checked by the caller of this function), the incoming blocks
728 // are also identical.
729 for (unsigned i = 0, e = PNL->getNumIncomingValues(); i != e; ++i) {
730 if (int Res =
731 cmpValues(PNL->getIncomingBlock(i), PNR->getIncomingBlock(i)))
732 return Res;
733 }
734 }
735 return 0;
736}
737
738// Determine whether two GEP operations perform the same underlying arithmetic.
739// Read method declaration comments for more details.
740int FunctionComparator::cmpGEPs(const GEPOperator *GEPL,
741 const GEPOperator *GEPR) const {
742 unsigned int ASL = GEPL->getPointerAddressSpace();
743 unsigned int ASR = GEPR->getPointerAddressSpace();
744
745 if (int Res = cmpNumbers(ASL, ASR))
746 return Res;
747
748 // When we have target data, we can reduce the GEP down to the value in bytes
749 // added to the address.
750 const DataLayout &DL = FnL->getParent()->getDataLayout();
751 unsigned OffsetBitWidth = DL.getIndexSizeInBits(ASL);
752 APInt OffsetL(OffsetBitWidth, 0), OffsetR(OffsetBitWidth, 0);
753 if (GEPL->accumulateConstantOffset(DL, OffsetL) &&
754 GEPR->accumulateConstantOffset(DL, OffsetR))
755 return cmpAPInts(OffsetL, OffsetR);
756 if (int Res =
758 return Res;
759
760 if (int Res = cmpNumbers(GEPL->getNumOperands(), GEPR->getNumOperands()))
761 return Res;
762
763 for (unsigned i = 0, e = GEPL->getNumOperands(); i != e; ++i) {
764 if (int Res = cmpValues(GEPL->getOperand(i), GEPR->getOperand(i)))
765 return Res;
766 }
767
768 return 0;
769}
770
771int FunctionComparator::cmpInlineAsm(const InlineAsm *L,
772 const InlineAsm *R) const {
773 // InlineAsm's are uniqued. If they are the same pointer, obviously they are
774 // the same, otherwise compare the fields.
775 if (L == R)
776 return 0;
777 if (int Res = cmpTypes(L->getFunctionType(), R->getFunctionType()))
778 return Res;
779 if (int Res = cmpMem(L->getAsmString(), R->getAsmString()))
780 return Res;
781 if (int Res = cmpMem(L->getConstraintString(), R->getConstraintString()))
782 return Res;
783 if (int Res = cmpNumbers(L->hasSideEffects(), R->hasSideEffects()))
784 return Res;
785 if (int Res = cmpNumbers(L->isAlignStack(), R->isAlignStack()))
786 return Res;
787 if (int Res = cmpNumbers(L->getDialect(), R->getDialect()))
788 return Res;
789 assert(L->getFunctionType() != R->getFunctionType());
790 return 0;
791}
792
793/// Compare two values used by the two functions under pair-wise comparison. If
794/// this is the first time the values are seen, they're added to the mapping so
795/// that we will detect mismatches on next use.
796/// See comments in declaration for more details.
797int FunctionComparator::cmpValues(const Value *L, const Value *R) const {
798 // Catch self-reference case.
799 if (L == FnL) {
800 if (R == FnR)
801 return 0;
802 return -1;
803 }
804 if (R == FnR) {
805 if (L == FnL)
806 return 0;
807 return 1;
808 }
809
810 const Constant *ConstL = dyn_cast<Constant>(L);
811 const Constant *ConstR = dyn_cast<Constant>(R);
812 if (ConstL && ConstR) {
813 if (L == R)
814 return 0;
815 return cmpConstants(ConstL, ConstR);
816 }
817
818 if (ConstL)
819 return 1;
820 if (ConstR)
821 return -1;
822
823 const InlineAsm *InlineAsmL = dyn_cast<InlineAsm>(L);
824 const InlineAsm *InlineAsmR = dyn_cast<InlineAsm>(R);
825
826 if (InlineAsmL && InlineAsmR)
827 return cmpInlineAsm(InlineAsmL, InlineAsmR);
828 if (InlineAsmL)
829 return 1;
830 if (InlineAsmR)
831 return -1;
832
833 auto LeftSN = sn_mapL.insert(std::make_pair(L, sn_mapL.size())),
834 RightSN = sn_mapR.insert(std::make_pair(R, sn_mapR.size()));
835
836 return cmpNumbers(LeftSN.first->second, RightSN.first->second);
837}
838
839// Test whether two basic blocks have equivalent behaviour.
841 const BasicBlock *BBR) const {
842 BasicBlock::const_iterator InstL = BBL->begin(), InstLE = BBL->end();
843 BasicBlock::const_iterator InstR = BBR->begin(), InstRE = BBR->end();
844
845 do {
846 bool needToCmpOperands = true;
847 if (int Res = cmpOperations(&*InstL, &*InstR, needToCmpOperands))
848 return Res;
849 if (needToCmpOperands) {
850 assert(InstL->getNumOperands() == InstR->getNumOperands());
851
852 for (unsigned i = 0, e = InstL->getNumOperands(); i != e; ++i) {
853 Value *OpL = InstL->getOperand(i);
854 Value *OpR = InstR->getOperand(i);
855 if (int Res = cmpValues(OpL, OpR))
856 return Res;
857 // cmpValues should ensure this is true.
858 assert(cmpTypes(OpL->getType(), OpR->getType()) == 0);
859 }
860 }
861
862 ++InstL;
863 ++InstR;
864 } while (InstL != InstLE && InstR != InstRE);
865
866 if (InstL != InstLE && InstR == InstRE)
867 return 1;
868 if (InstL == InstLE && InstR != InstRE)
869 return -1;
870 return 0;
871}
872
874 if (int Res = cmpAttrs(FnL->getAttributes(), FnR->getAttributes()))
875 return Res;
876
877 if (int Res = cmpNumbers(FnL->hasGC(), FnR->hasGC()))
878 return Res;
879
880 if (FnL->hasGC()) {
881 if (int Res = cmpMem(FnL->getGC(), FnR->getGC()))
882 return Res;
883 }
884
885 if (int Res = cmpNumbers(FnL->hasSection(), FnR->hasSection()))
886 return Res;
887
888 if (FnL->hasSection()) {
889 if (int Res = cmpMem(FnL->getSection(), FnR->getSection()))
890 return Res;
891 }
892
893 if (int Res = cmpNumbers(FnL->isVarArg(), FnR->isVarArg()))
894 return Res;
895
896 // TODO: if it's internal and only used in direct calls, we could handle this
897 // case too.
898 if (int Res = cmpNumbers(FnL->getCallingConv(), FnR->getCallingConv()))
899 return Res;
900
901 if (int Res = cmpTypes(FnL->getFunctionType(), FnR->getFunctionType()))
902 return Res;
903
904 assert(FnL->arg_size() == FnR->arg_size() &&
905 "Identically typed functions have different numbers of args!");
906
907 // Visit the arguments so that they get enumerated in the order they're
908 // passed in.
910 ArgRI = FnR->arg_begin(),
911 ArgLE = FnL->arg_end();
912 ArgLI != ArgLE; ++ArgLI, ++ArgRI) {
913 if (cmpValues(&*ArgLI, &*ArgRI) != 0)
914 llvm_unreachable("Arguments repeat!");
915 }
916 return 0;
917}
918
919// Test whether the two functions have equivalent behaviour.
921 beginCompare();
922
923 if (int Res = compareSignature())
924 return Res;
925
926 // We do a CFG-ordered walk since the actual ordering of the blocks in the
927 // linked list is immaterial. Our walk starts at the entry block for both
928 // functions, then takes each block from each terminator in order. As an
929 // artifact, this also means that unreachable blocks are ignored.
931 SmallPtrSet<const BasicBlock *, 32> VisitedBBs; // in terms of F1.
932
933 FnLBBs.push_back(&FnL->getEntryBlock());
934 FnRBBs.push_back(&FnR->getEntryBlock());
935
936 VisitedBBs.insert(FnLBBs[0]);
937 while (!FnLBBs.empty()) {
938 const BasicBlock *BBL = FnLBBs.pop_back_val();
939 const BasicBlock *BBR = FnRBBs.pop_back_val();
940
941 if (int Res = cmpValues(BBL, BBR))
942 return Res;
943
944 if (int Res = cmpBasicBlocks(BBL, BBR))
945 return Res;
946
947 const Instruction *TermL = BBL->getTerminator();
948 const Instruction *TermR = BBR->getTerminator();
949
950 assert(TermL->getNumSuccessors() == TermR->getNumSuccessors());
951 for (unsigned i = 0, e = TermL->getNumSuccessors(); i != e; ++i) {
952 if (!VisitedBBs.insert(TermL->getSuccessor(i)).second)
953 continue;
954
955 FnLBBs.push_back(TermL->getSuccessor(i));
956 FnRBBs.push_back(TermR->getSuccessor(i));
957 }
958 }
959 return 0;
960}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define LLVM_DEBUG(X)
Definition: Debug.h:101
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
This file contains the declarations for metadata subclasses.
Module.h This file contains the declarations for the Module class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SI optimize exec mask operations pre RA
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
Class for arbitrary precision integers.
Definition: APInt.h:76
an instruction to allocate memory on the stack
Definition: Instructions.h:58
This class represents an incoming formal argument to a Function.
Definition: Argument.h:28
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
An instruction that atomically checks whether a specified value is in a memory location,...
Definition: Instructions.h:513
an instruction that atomically reads a memory location, combines it with another value,...
Definition: Instructions.h:718
iterator begin() const
Definition: Attributes.cpp:878
iterator end() const
Definition: Attributes.cpp:882
Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
Definition: Attributes.cpp:290
bool isTypeAttribute() const
Return true if the attribute is a type attribute.
Definition: Attributes.cpp:286
Type * getValueAsType() const
Return the attribute's value as a Type.
Definition: Attributes.cpp:325
LLVM Basic Block Representation.
Definition: BasicBlock.h:56
iterator end()
Definition: BasicBlock.h:337
iterator begin()
Instruction iterator methods.
Definition: BasicBlock.h:335
InstListType::const_iterator const_iterator
Definition: BasicBlock.h:88
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition: BasicBlock.h:127
The address of a basic block.
Definition: Constants.h:874
Function * getFunction() const
Definition: Constants.h:902
BasicBlock * getBasicBlock() const
Definition: Constants.h:903
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1190
OperandBundleUse getOperandBundleAt(unsigned Index) const
Return the operand bundle at a specific index.
Definition: InstrTypes.h:2023
unsigned getNumOperandBundles() const
Return the number of operand bundles associated with this User.
Definition: InstrTypes.h:1967
This class represents a function call, abstracting a target machine's calling convention.
This class is the base class for the comparison instructions.
Definition: InstrTypes.h:701
ConstantArray - Constant Array Declarations.
Definition: Constants.h:408
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:997
Constant Vector Declarations.
Definition: Constants.h:492
This is an important base class in LLVM.
Definition: Constant.h:41
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:110
This instruction extracts a struct member or array element value from an aggregate value.
An instruction for ordering other memory operations.
Definition: Instructions.h:436
int cmpBasicBlocks(const BasicBlock *BBL, const BasicBlock *BBR) const
Test whether two basic blocks have equivalent behaviour.
int compareSignature() const
Compares the signature and other general attributes of the two functions.
int cmpMem(StringRef L, StringRef R) const
int compare()
Test whether the two functions have equivalent behaviour.
int cmpAPFloats(const APFloat &L, const APFloat &R) const
int cmpTypes(Type *TyL, Type *TyR) const
cmpType - compares two types, defines total ordering among the types set.
int cmpOperations(const Instruction *L, const Instruction *R, bool &needToCmpOperands) const
Compare two Instructions for equivalence, similar to Instruction::isSameOperationAs.
int cmpNumbers(uint64_t L, uint64_t R) const
int cmpAligns(Align L, Align R) const
void beginCompare()
Start the comparison.
int cmpValues(const Value *L, const Value *R) const
Assign or look up previously assigned numbers for the two values, and return whether the numbers are ...
int cmpGlobalValues(GlobalValue *L, GlobalValue *R) const
Compares two global values by number.
int cmpConstants(const Constant *L, const Constant *R) const
Constants comparison.
int cmpAPInts(const APInt &L, const APInt &R) const
Class to represent function types.
Definition: DerivedTypes.h:103
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
Definition: DerivedTypes.h:139
Type * getParamType(unsigned i) const
Parameter type accessors.
Definition: DerivedTypes.h:135
bool isVarArg() const
Definition: DerivedTypes.h:123
Type * getReturnType() const
Definition: DerivedTypes.h:124
const BasicBlock & getEntryBlock() const
Definition: Function.h:747
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:176
bool hasGC() const
hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm to use during code generatio...
Definition: Function.h:307
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition: Function.h:239
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition: Function.h:315
arg_iterator arg_end()
Definition: Function.h:787
arg_iterator arg_begin()
Definition: Function.h:778
const std::string & getGC() const
Definition: Function.cpp:732
size_t arg_size() const
Definition: Function.h:811
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Definition: Function.h:189
Type * getSourceElementType() const
Definition: Operator.cpp:54
bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset, function_ref< bool(Value &, APInt &)> ExternalAnalysis=nullptr) const
Accumulate the constant address offset of this GEP if possible.
Definition: Operator.cpp:91
unsigned getPointerAddressSpace() const
Method to return the address space of the pointer operand.
Definition: Operator.h:433
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Definition: Instructions.h:940
uint64_t getNumber(GlobalValue *Global)
StringRef getSection() const
Get the custom section of this global if it has one.
Definition: GlobalObject.h:117
bool hasSection() const
Check if this global has a custom object file section.
Definition: GlobalObject.h:109
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:652
This instruction inserts a struct field of array element value into an aggregate value.
unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Definition: Instruction.h:195
An instruction for reading from memory.
Definition: Instructions.h:177
Metadata node.
Definition: Metadata.h:950
Root of the metadata hierarchy.
Definition: Metadata.h:61
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Definition: Module.h:254
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Class to represent pointers.
Definition: DerivedTypes.h:643
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Definition: DerivedTypes.h:690
This instruction constructs a fixed permutation of two input vectors.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:366
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:451
bool empty() const
Definition: SmallVector.h:94
size_t size() const
Definition: SmallVector.h:91
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
An instruction for storing to memory.
Definition: Instructions.h:301
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Class to represent struct types.
Definition: DerivedTypes.h:213
bool isPacked() const
Definition: DerivedTypes.h:275
unsigned getNumElements() const
Random access to the elements.
Definition: DerivedTypes.h:338
Type * getElementType(unsigned N) const
Definition: DerivedTypes.h:339
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
@ FunctionTyID
Functions.
Definition: Type.h:72
@ ArrayTyID
Arrays.
Definition: Type.h:75
@ VoidTyID
type with no size
Definition: Type.h:63
@ ScalableVectorTyID
Scalable SIMD vector type.
Definition: Type.h:77
@ LabelTyID
Labels.
Definition: Type.h:64
@ FloatTyID
32-bit floating point type
Definition: Type.h:58
@ StructTyID
Structures.
Definition: Type.h:74
@ IntegerTyID
Arbitrary bit width integers.
Definition: Type.h:71
@ FixedVectorTyID
Fixed width SIMD vector type.
Definition: Type.h:76
@ DoubleTyID
64-bit floating point type
Definition: Type.h:59
@ X86_FP80TyID
80-bit floating point type (X87)
Definition: Type.h:60
@ PPC_FP128TyID
128-bit floating point type (two 64-bits, PowerPC)
Definition: Type.h:62
@ MetadataTyID
Metadata.
Definition: Type.h:65
@ TokenTyID
Tokens.
Definition: Type.h:68
@ PointerTyID
Pointers.
Definition: Type.h:73
@ FP128TyID
128-bit floating point type (112-bit significand)
Definition: Type.h:61
bool isFirstClassType() const
Return true if the type is "first class", meaning it is a valid type for a Value.
Definition: Type.h:281
TypeID getTypeID() const
Return the type id for the type.
Definition: Type.h:137
Value * getOperand(unsigned i) const
Definition: User.h:169
unsigned getNumOperands() const
Definition: User.h:191
LLVM Value Representation.
Definition: Value.h:74
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
AtomicOrdering
Atomic ordering for LLVM's memory model.
#define N
static ExponentType semanticsMinExponent(const fltSemantics &)
Definition: APFloat.cpp:300
static unsigned int semanticsSizeInBits(const fltSemantics &)
Definition: APFloat.cpp:303
static ExponentType semanticsMaxExponent(const fltSemantics &)
Definition: APFloat.cpp:296
static unsigned int semanticsPrecision(const fltSemantics &)
Definition: APFloat.cpp:292
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39