diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 374db21f9b5c5..3f4f18259df16 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -3355,9 +3355,10 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, !(type->isUnsignedIntegerType() && CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) && CGF.getLangOpts().getSignedOverflowBehavior() != - LangOptions::SOB_Trapping) { - llvm::AtomicRMWInst::BinOp aop = isInc ? llvm::AtomicRMWInst::Add : - llvm::AtomicRMWInst::Sub; + LangOptions::SOB_Trapping && + !type->isCHERICapabilityType(CGF.getContext())) { + llvm::AtomicRMWInst::BinOp aop = + isInc ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::Sub; llvm::Instruction::BinaryOps op = isInc ? llvm::Instruction::Add : llvm::Instruction::Sub; llvm::Value *amt = CGF.EmitToMemory( diff --git a/clang/test/CodeGen/cheri/riscv/cheriot-atomic-uintptr.c b/clang/test/CodeGen/cheri/riscv/cheriot-atomic-uintptr.c new file mode 100644 index 0000000000000..4eb0ee2cb8e61 --- /dev/null +++ b/clang/test/CodeGen/cheri/riscv/cheriot-atomic-uintptr.c @@ -0,0 +1,38 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 %s -o - "-triple" "riscv32cheriot-unknown-unknown" "-emit-llvm" "-mframe-pointer=none" "-mcmodel=small" "-target-abi" "cheriot" "-Oz" "-Werror" -std=c2x | FileCheck %s + +// Check that we can generate code for C11 atomic increment of uintptr + +// CHECK-LABEL: define dso_local void @test1( +// CHECK-SAME: ) local_unnamed_addr addrspace(200) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*]]: +// CHECK-NEXT: [[P:%.*]] = alloca ptr addrspace(200), align 8, addrspace(200) +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca ptr addrspace(200), align 8, addrspace(200) +// CHECK-NEXT: [[ATOMIC_TEMP1:%.*]] = alloca ptr addrspace(200), align 8, addrspace(200) +// CHECK-NEXT: [[ATOMIC_TEMP2:%.*]] = alloca ptr addrspace(200), align 8, addrspace(200) +// CHECK-NEXT: call void @llvm.lifetime.start.p200(i64 8, ptr addrspace(200) nonnull [[P]]) #[[ATTR4:[0-9]+]] +// CHECK-NEXT: call cherilibcallcc void @__atomic_load(i32 noundef 8, ptr addrspace(200) noundef nonnull [[P]], ptr addrspace(200) noundef nonnull [[ATOMIC_TEMP]], i32 noundef 5) #[[ATTR5:[0-9]+]] +// CHECK-NEXT: br label %[[ATOMIC_OP:.*]] +// CHECK: [[ATOMIC_OP]]: +// CHECK-NEXT: [[DOTIN:%.*]] = phi ptr addrspace(200) [ [[ATOMIC_TEMP]], %[[ENTRY]] ], [ [[ATOMIC_TEMP1]], %[[ATOMIC_OP]] ] +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(200), ptr addrspace(200) [[DOTIN]], align 8, !tbaa [[TBAA7:![0-9]+]] +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr addrspace(200) [[TMP0]], i32 1 +// CHECK-NEXT: store ptr addrspace(200) [[TMP0]], ptr addrspace(200) [[ATOMIC_TEMP1]], align 8, !tbaa [[TBAA11:![0-9]+]] +// CHECK-NEXT: store ptr addrspace(200) [[TMP1]], ptr addrspace(200) [[ATOMIC_TEMP2]], align 8, !tbaa [[TBAA11]] +// CHECK-NEXT: [[CALL:%.*]] = call cherilibcallcc zeroext i1 @__atomic_compare_exchange(i32 noundef 8, ptr addrspace(200) noundef nonnull [[P]], ptr addrspace(200) noundef nonnull [[ATOMIC_TEMP1]], ptr addrspace(200) noundef nonnull [[ATOMIC_TEMP2]], i32 noundef 5, i32 noundef 5) #[[ATTR5]] +// CHECK-NEXT: br i1 [[CALL]], label %[[ATOMIC_CONT:.*]], label %[[ATOMIC_OP]] +// CHECK: [[ATOMIC_CONT]]: +// CHECK-NEXT: call void @llvm.lifetime.end.p200(i64 8, ptr addrspace(200) nonnull [[P]]) #[[ATTR4]] +// CHECK-NEXT: ret void +// +void test1() { + _Atomic(__UINTPTR_TYPE__) p; + ++p; +} +//. +// CHECK: [[TBAA7]] = !{[[META8:![0-9]+]], [[META8]], i64 0} +// CHECK: [[META8]] = !{!"unsigned __intcap", [[META9:![0-9]+]], i64 0} +// CHECK: [[META9]] = !{!"omnipotent char", [[META10:![0-9]+]], i64 0} +// CHECK: [[META10]] = !{!"Simple C/C++ TBAA"} +// CHECK: [[TBAA11]] = !{[[META9]], [[META9]], i64 0} +//.