diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index bb671c5ab5813a..a1dce741c78a11 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3882,6 +3882,8 @@ llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) { TrapCall->addFnAttr(A); } + if (InNoMergeAttributedStmt) + TrapCall->addFnAttr(llvm::Attribute::NoMerge); return TrapCall; } diff --git a/clang/test/CodeGen/attr-nomerge.cpp b/clang/test/CodeGen/attr-nomerge.cpp index 7305fb73cf1dcd..b643920adde497 100644 --- a/clang/test/CodeGen/attr-nomerge.cpp +++ b/clang/test/CodeGen/attr-nomerge.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-unknown-linux-gnu -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -fms-extensions -o - | FileCheck %s class A { public: @@ -42,6 +42,9 @@ void foo(int i, A *ap, B *bp) { A *newA = new B(); delete newA; + [[clang::nomerge]] __builtin_trap(); + [[clang::nomerge]] __debugbreak(); + [[clang::nomerge]] __builtin_verbose_trap("check null", "Argument must not be null."); } int g(int i); @@ -97,6 +100,9 @@ void something_else_again() { // CHECK: load ptr, ptr // CHECK: %[[AG:.*]] = load ptr, ptr // CHECK-NEXT: call void %[[AG]](ptr {{.*}}) #[[ATTR1]] +// CHECK: call void @llvm.trap() #[[ATTR0]] +// CHECK: call void @llvm.debugtrap() #[[ATTR0]] +// CHECK: call void @llvm.trap() #[[ATTR0]] // CHECK: call void @_ZN1AD1Ev(ptr {{.*}}) #[[ATTR1]] // CHECK-DAG: attributes #[[ATTR0]] = {{{.*}}nomerge{{.*}}} diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 9f5e6466309e96..a035fee6aafca3 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -7448,6 +7448,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, break; default: llvm_unreachable("unknown trap intrinsic"); } + DAG.addNoMergeSiteInfo(DAG.getRoot().getNode(), + I.hasFnAttr(Attribute::NoMerge)); return; } TargetLowering::ArgListTy Args; @@ -7464,7 +7466,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, DAG.getExternalSymbol(TrapFuncName.data(), TLI.getPointerTy(DAG.getDataLayout())), std::move(Args)); - + CLI.NoMerge = I.hasFnAttr(Attribute::NoMerge); std::pair Result = TLI.LowerCallTo(CLI); DAG.setRoot(Result.second); return; diff --git a/llvm/test/CodeGen/X86/nomerge.ll b/llvm/test/CodeGen/X86/nomerge.ll index efbadf5b6911f4..f0aedcb90c4ada 100644 --- a/llvm/test/CodeGen/X86/nomerge.ll +++ b/llvm/test/CodeGen/X86/nomerge.ll @@ -62,4 +62,96 @@ if.end: declare dso_local void @bar() +define void @nomerge_trap(i32 %i) { +; CHECK-LABEL: nomerge_trap: +; CHECK: # %bb.0: # %entry +; CHECK: # %bb.1: # %entry +; CHECK: # %bb.2: # %if.then +; CHECK-NEXT: ud2 +; CHECK-NEXT: LBB{{.*}}: # %if.then2 +; CHECK-NEXT: ud2 +; CHECK-NEXT: .LBB{{.*}}: # %if.end3 +; CHECK-NEXT: ud2 +entry: + switch i32 %i, label %if.end3 [ + i32 5, label %if.then + i32 7, label %if.then2 + ] + +if.then: + tail call void @llvm.trap() #0 + unreachable + +if.then2: + tail call void @llvm.trap() #0 + unreachable + +if.end3: + tail call void @llvm.trap() #0 + unreachable +} + +declare dso_local void @llvm.trap() + +define void @nomerge_debugtrap(i32 %i) { +; CHECK-LABEL: nomerge_debugtrap: +; CHECK: # %bb.0: # %entry +; CHECK: # %bb.1: # %entry +; CHECK: # %bb.2: # %if.then +; CHECK-NEXT: int3 +; CHECK-NEXT: LBB{{.*}}: # %if.then2 +; CHECK-NEXT: int3 +; CHECK-NEXT: .LBB{{.*}}: # %if.end3 +; CHECK-NEXT: int3 +entry: + switch i32 %i, label %if.end3 [ + i32 5, label %if.then + i32 7, label %if.then2 + ] + +if.then: + tail call void @llvm.debugtrap() #0 + unreachable + +if.then2: + tail call void @llvm.debugtrap() #0 + unreachable + +if.end3: + tail call void @llvm.debugtrap() #0 + unreachable +} + +define void @nomerge_named_debugtrap(i32 %i) { +; CHECK-LABEL: nomerge_named_debugtrap: +; CHECK: # %bb.0: # %entry +; CHECK: # %bb.1: # %entry +; CHECK: # %bb.2: # %if.then +; CHECK-NEXT: callq trap_func@PLT +; CHECK-NEXT: LBB{{.*}}: # %if.then2 +; CHECK-NEXT: callq trap_func@PLT +; CHECK-NEXT: .LBB{{.*}}: # %if.end3 +; CHECK-NEXT: callq trap_func@PLT +entry: + switch i32 %i, label %if.end3 [ + i32 5, label %if.then + i32 7, label %if.then2 + ] + +if.then: + tail call void @llvm.debugtrap() #1 + unreachable + +if.then2: + tail call void @llvm.debugtrap() #1 + unreachable + +if.end3: + tail call void @llvm.debugtrap() #1 + unreachable +} + +declare dso_local void @llvm.debugtrap() + attributes #0 = { nomerge } +attributes #1 = { nomerge "trap-func-name"="trap_func" } diff --git a/llvm/test/MC/AArch64/local-bounds-single-trap.ll b/llvm/test/MC/AArch64/local-bounds-single-trap.ll index 53a0e010537f09..6a017e24ab3cdf 100644 --- a/llvm/test/MC/AArch64/local-bounds-single-trap.ll +++ b/llvm/test/MC/AArch64/local-bounds-single-trap.ll @@ -21,11 +21,11 @@ entry: ; CHECK-ASM: add x10, x10, :lo12:B ; CHECK-ASM: strb wzr, [x10, x8] ; CHECK-ASM: cmp x9, #10 -; CHECK-ASM: b.hi .LBB0_5 +; CHECK-ASM: b.hi .LBB0_6 ; CHECK-ASM: // %bb.3: ; CHECK-ASM: mov w8, #10 // =0xa ; CHECK-ASM: sub x8, x8, x9 -; CHECK-ASM: cbz x8, .LBB0_5 +; CHECK-ASM: cbz x8, .LBB0_6 ; CHECK-ASM: // %bb.4: ; CHECK-ASM: adrp x8, B2 ; CHECK-ASM: add x8, x8, :lo12:B2 @@ -33,9 +33,11 @@ entry: ; CHECK-ASM: add sp, sp, #16 ; CHECK-ASM: .cfi_def_cfa_offset 0 ; CHECK-ASM: ret -; CHECK-ASM: .LBB0_5: // %trap3 -; CHECK-ASM: .cfi_restore_state -; CHECK-ASM: brk #0x1 +; CHECK-ASM: .LBB0_5: // %trap +; CHECK-ASM: .cfi_restore_state +; CHECK-ASM: brk #0x1 +; CHECK-ASM: .LBB0_6: // %trap3 +; CHECK-ASM: brk #0x1 %i.addr = alloca i32, align 4 %k.addr = alloca i32, align 4 store i32 %i, ptr %i.addr, align 4