|
21 | 21 | using namespace clang; |
22 | 22 | using namespace clang::CIRGen; |
23 | 23 |
|
| 24 | +// OG has unordered comparison as a form of optimization in addition to |
| 25 | +// ordered comparison, while CIR doesn't. |
| 26 | +// |
| 27 | +// This means that we can't encode the comparison code of UGT (unordered |
| 28 | +// greater than), at least not at the CIR level. |
| 29 | +// |
| 30 | +// The boolean shouldInvert compensates for this. |
| 31 | +// For example: to get to the comparison code UGT, we pass in |
| 32 | +// emitVectorFCmp (OLE, shouldInvert = true) since OLE is the inverse of UGT. |
| 33 | + |
| 34 | +// There are several ways to support this otherwise: |
| 35 | +// - register extra CmpOpKind for unordered comparison types and build the |
| 36 | +// translation code for |
| 37 | +// to go from CIR -> LLVM dialect. Notice we get this naturally with |
| 38 | +// shouldInvert, benefiting from existing infrastructure, albeit having to |
| 39 | +// generate an extra `not` at CIR). |
| 40 | +// - Just add extra comparison code to a new VecCmpOpKind instead of |
| 41 | +// cluttering CmpOpKind. |
| 42 | +// - Add a boolean in VecCmpOp to indicate if it's doing unordered or ordered |
| 43 | +// comparison |
| 44 | +// - Just emit the intrinsics call instead of calling this helper, see how the |
| 45 | +// LLVM lowering handles this. |
| 46 | +static mlir::Value emitVectorFCmp(CIRGenBuilderTy &builder, |
| 47 | + llvm::SmallVector<mlir::Value> &ops, |
| 48 | + mlir::Location loc, cir::CmpOpKind pred, |
| 49 | + bool shouldInvert) { |
| 50 | + assert(!cir::MissingFeatures::cgFPOptionsRAII()); |
| 51 | + // TODO(cir): Add isSignaling boolean once emitConstrainedFPCall implemented |
| 52 | + assert(!cir::MissingFeatures::emitConstrainedFPCall()); |
| 53 | + mlir::Value cmp = builder.createVecCompare(loc, pred, ops[0], ops[1]); |
| 54 | + mlir::Value bitCast = builder.createBitcast( |
| 55 | + shouldInvert ? builder.createNot(cmp) : cmp, ops[0].getType()); |
| 56 | + return bitCast; |
| 57 | +} |
| 58 | + |
24 | 59 | mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, |
25 | 60 | const CallExpr *expr) { |
26 | 61 | if (builtinID == Builtin::BI__builtin_cpu_is) { |
@@ -52,45 +87,9 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, |
52 | 87 | assert(error == ASTContext::GE_None && |
53 | 88 | "builtinID should be checked before calling emitX86BuiltinExpr"); |
54 | 89 | for (auto [idx, arg] : llvm::enumerate(expr->arguments())) { |
55 | | - ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, idx, expr)); |
| 90 | + ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, idx, arg)); |
56 | 91 | } |
57 | 92 |
|
58 | | - // OG has unordered comparison as a form of optimization in addition to |
59 | | - // ordered comparison, while CIR doesn't. |
60 | | - // |
61 | | - // This means that we can't encode the comparison code of UGT (unordered |
62 | | - // greater than), at least not at the CIR level. |
63 | | - // |
64 | | - // The boolean shouldInvert compensates for this. |
65 | | - // For example: to get to the comparison code UGT, we pass in |
66 | | - // emitVectorFCmp (OLE, shouldInvert = true) since OLE is the inverse of UGT. |
67 | | - |
68 | | - // There are several ways to support this otherwise: |
69 | | - // - register extra CmpOpKind for unordered comparison types and build the |
70 | | - // translation code for |
71 | | - // to go from CIR -> LLVM dialect. Notice we get this naturally with |
72 | | - // shouldInvert, benefiting from existing infrastructure, albeit having to |
73 | | - // generate an extra `not` at CIR). |
74 | | - // - Just add extra comparison code to a new VecCmpOpKind instead of |
75 | | - // cluttering CmpOpKind. |
76 | | - // - Add a boolean in VecCmpOp to indicate if it's doing unordered or ordered |
77 | | - // comparison |
78 | | - // - Just emit the intrinsics call instead of calling this helper, see how the |
79 | | - // LLVM lowering handles this. |
80 | | - auto emitVectorFCmp = [this, &ops, &expr](cir::CmpOpKind pred, |
81 | | - bool shouldInvert, |
82 | | - bool isSignaling) { |
83 | | - assert(!cir::MissingFeatures::cgFPOptionsRAII()); |
84 | | - auto loc = getLoc(expr->getExprLoc()); |
85 | | - // TODO: Add isSignaling boolean once emitConstrainedFPCall implemented |
86 | | - assert(!cir::MissingFeatures::emitConstrainedFPCall() && |
87 | | - "constrained FP compare NYI"); |
88 | | - mlir::Value cmp = builder.createVecCompare(loc, pred, ops[0], ops[1]); |
89 | | - mlir::Value bitCast = builder.createBitcast( |
90 | | - shouldInvert ? builder.createNot(cmp) : cmp, ops[0].getType()); |
91 | | - return bitCast; |
92 | | - }; |
93 | | - |
94 | 93 | switch (builtinID) { |
95 | 94 | default: |
96 | 95 | return {}; |
@@ -764,12 +763,12 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, |
764 | 763 | return {}; |
765 | 764 | case X86::BI__builtin_ia32_cmpnltps: |
766 | 765 | case X86::BI__builtin_ia32_cmpnltpd: |
767 | | - return emitVectorFCmp(cir::CmpOpKind::lt, /*shouldInvert=*/true, |
768 | | - /*isSignaling=*/true); |
| 766 | + return emitVectorFCmp(builder, ops, getLoc(expr->getExprLoc()), |
| 767 | + cir::CmpOpKind::lt, /*shouldInvert=*/true); |
769 | 768 | case X86::BI__builtin_ia32_cmpnleps: |
770 | 769 | case X86::BI__builtin_ia32_cmpnlepd: |
771 | | - return emitVectorFCmp(cir::CmpOpKind::le, /*shouldInvert=*/true, |
772 | | - /*isSignaling=*/true); |
| 770 | + return emitVectorFCmp(builder, ops, getLoc(expr->getExprLoc()), |
| 771 | + cir::CmpOpKind::le, /*shouldInvert=*/true); |
773 | 772 | case X86::BI__builtin_ia32_cmpordps: |
774 | 773 | case X86::BI__builtin_ia32_cmpordpd: |
775 | 774 | case X86::BI__builtin_ia32_cmpph128_mask: |
|
0 commit comments