Skip to content

Commit

Permalink
[CIR][CIRGen] Add alignment attribute to AtomicCmpXchg (#1327)
Browse files Browse the repository at this point in the history
There is an `alignment` attribute in MLIR's LLVMIR Dialect
https://github.com/llvm/clangir/blob/a7383c9d05165d16edba857ddc86e5d29d94d2cc/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td#L1880

When Clang builds IR, it adds an alignment automatically

https://github.com/llvm/clangir/blob/a7383c9d05165d16edba857ddc86e5d29d94d2cc/clang/lib/CodeGen/CGBuilder.h#L168-L177

This PR does the same thing for ClangIR.

Closes: #1275
  • Loading branch information
FantasqueX authored Feb 11, 2025
1 parent 37fab7c commit c4409e1
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 52 deletions.
2 changes: 2 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -5390,6 +5390,7 @@ def AtomicCmpXchg : CIR_Op<"atomic.cmp_xchg",
CIR_AnyType:$desired,
Arg<MemOrder, "success memory order">:$succ_order,
Arg<MemOrder, "failure memory order">:$fail_order,
OptionalAttr<I64Attr>:$alignment,
UnitAttr:$weak,
UnitAttr:$is_volatile);

Expand All @@ -5401,6 +5402,7 @@ def AtomicCmpXchg : CIR_Op<"atomic.cmp_xchg",
`success` `=` $succ_order `,`
`failure` `=` $fail_order
`)`
(`align` `(` $alignment^ `)`)?
(`weak` $weak^)?
(`volatile` $is_volatile^)?
`:` `(` type($old) `,` type($cmp) `)` attr-dict
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,9 @@ static void emitAtomicCmpXchg(CIRGenFunction &CGF, AtomicExpr *E, bool IsWeak,
auto boolTy = builder.getBoolTy();
auto cmpxchg = builder.create<cir::AtomicCmpXchg>(
loc, Expected.getType(), boolTy, Ptr.getPointer(), Expected, Desired,
SuccessOrder, FailureOrder);
cir::MemOrderAttr::get(&CGF.getMLIRContext(), SuccessOrder),
cir::MemOrderAttr::get(&CGF.getMLIRContext(), FailureOrder),
builder.getI64IntegerAttr(Ptr.getAlignment().getAsAlign().value()));
cmpxchg.setIsVolatile(E->isVolatile());
cmpxchg.setWeak(IsWeak);

Expand Down
7 changes: 5 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,11 @@ static mlir::Value MakeAtomicCmpXchgValue(CIRGenFunction &cgf,
auto op = builder.create<cir::AtomicCmpXchg>(
cgf.getLoc(expr->getSourceRange()), cmpVal.getType(), builder.getBoolTy(),
destAddr.getPointer(), cmpVal, newVal,
cir::MemOrder::SequentiallyConsistent,
cir::MemOrder::SequentiallyConsistent);
MemOrderAttr::get(&cgf.getMLIRContext(),
cir::MemOrder::SequentiallyConsistent),
MemOrderAttr::get(&cgf.getMLIRContext(),
cir::MemOrder::SequentiallyConsistent),
builder.getI64IntegerAttr(destAddr.getAlignment().getAsAlign().value()));

return returnBool ? op.getResult(1) : op.getResult(0);
}
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3202,6 +3202,7 @@ mlir::LogicalResult CIRToLLVMAtomicCmpXchgLowering::matchAndRewrite(
op.getLoc(), adaptor.getPtr(), expected, desired,
getLLVMAtomicOrder(adaptor.getSuccOrder()),
getLLVMAtomicOrder(adaptor.getFailOrder()));
cmpxchg.setAlignment(adaptor.getAlignment());
cmpxchg.setWeak(adaptor.getWeak());
cmpxchg.setVolatile_(adaptor.getIsVolatile());

Expand Down
30 changes: 15 additions & 15 deletions clang/test/CIR/CodeGen/atomic-runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(default, []) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = relaxed, failure = relaxed) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = relaxed, failure = relaxed) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -131,7 +131,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i]) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = relaxed, failure = acquire) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = relaxed, failure = acquire) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -142,7 +142,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(equal, [#cir.int<5> : !s32i]) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = relaxed, failure = seq_cst) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = relaxed, failure = seq_cst) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -158,7 +158,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(default, []) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = acquire, failure = relaxed) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = acquire, failure = relaxed) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -169,7 +169,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i]) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = acquire, failure = acquire) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = acquire, failure = acquire) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -180,7 +180,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(equal, [#cir.int<5> : !s32i]) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = acquire, failure = seq_cst) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = acquire, failure = seq_cst) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -196,7 +196,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(default, []) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = release, failure = relaxed) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = release, failure = relaxed) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -207,7 +207,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i]) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = release, failure = acquire) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = release, failure = acquire) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -218,7 +218,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(equal, [#cir.int<5> : !s32i]) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = release, failure = seq_cst) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = release, failure = seq_cst) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -234,7 +234,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(default, []) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = acq_rel, failure = relaxed) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = acq_rel, failure = relaxed) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -245,7 +245,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i]) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = acq_rel, failure = acquire) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = acq_rel, failure = acquire) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -256,7 +256,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(equal, [#cir.int<5> : !s32i]) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = acq_rel, failure = seq_cst) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = acq_rel, failure = seq_cst) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -272,7 +272,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(default, []) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = seq_cst, failure = relaxed) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = seq_cst, failure = relaxed) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -283,7 +283,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i]) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = seq_cst, failure = acquire) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = seq_cst, failure = acquire) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -294,7 +294,7 @@ bool atomic_compare_exchange_n(int* ptr, int* expected,
// CHECK: cir.case(equal, [#cir.int<5> : !s32i]) {
// CHECK: %[[expected:.*]] = cir.load %[[expected_addr]] : !cir.ptr<!s32i>, !s32i
// CHECK: %[[desired:.*]] = cir.load %[[desired_var]] : !cir.ptr<!s32i>, !s32i
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = seq_cst, failure = seq_cst) : (!s32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg(%[[ptr]] : !cir.ptr<!s32i>, %[[expected]] : !s32i, %[[desired]] : !s32i, success = seq_cst, failure = seq_cst) align(4) : (!s32i, !cir.bool)
// CHECK: %[[succeeded:.*]] = cir.unary(not, %cmp) : !cir.bool, !cir.bool
// CHECK: cir.if %[[succeeded]] {
// CHECK: cir.store %old, %[[expected_addr]] : !s32i, !cir.ptr<!s32i>
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/atomic-xchg-field.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ void structAtomicExchange(unsigned referenceCount, wPtr item) {
}

// CHECK-LABEL: @structAtomicExchange
// CHECK: %old, %cmp = cir.atomic.cmp_xchg({{.*}} : !cir.ptr<!u32i>, {{.*}} : !u32i, {{.*}} : !u32i, success = seq_cst, failure = seq_cst) weak : (!u32i, !cir.bool)
// CHECK: %old, %cmp = cir.atomic.cmp_xchg({{.*}} : !cir.ptr<!u32i>, {{.*}} : !u32i, {{.*}} : !u32i, success = seq_cst, failure = seq_cst) align(8) weak : (!u32i, !cir.bool)

// LLVM-LABEL: @structAtomicExchange
// LLVM: load i32
// LLVM: add i32
// LLVM: store i32
// LLVM: %[[EXP:.*]] = load i32
// LLVM: %[[DES:.*]] = load i32
// LLVM: %[[RES:.*]] = cmpxchg weak ptr %9, i32 %[[EXP]], i32 %[[DES]] seq_cst seq_cst
// LLVM: %[[RES:.*]] = cmpxchg weak ptr %9, i32 %[[EXP]], i32 %[[DES]] seq_cst seq_cst, align 8
// LLVM: %[[OLD:.*]] = extractvalue { i32, i1 } %[[RES]], 0
// LLVM: %[[CMP:.*]] = extractvalue { i32, i1 } %[[RES]], 1
// LLVM: %[[FAIL:.*]] = xor i1 %[[CMP]], true
Expand Down
Loading

0 comments on commit c4409e1

Please sign in to comment.