diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3623,7 +3623,8 @@ CGM.getCodeGenOpts().TrapFuncName); 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 --- a/clang/test/CodeGen/attr-nomerge.cpp +++ b/clang/test/CodeGen/attr-nomerge.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -S -emit-llvm %s -triple x86_64-unknown-linux-gnu -o - | FileCheck %s +// RUN: %clang_cc1 -S -emit-llvm %s -fms-extensions -o - | FileCheck %s class A { public: @@ -40,6 +40,9 @@ A *newA = new B(); delete newA; + + [[clang::nomerge]] __builtin_trap(); + [[clang::nomerge]] __debugbreak(); } int g(int i); @@ -93,6 +96,8 @@ // 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 @_ZN1AD1Ev(ptr {{.*}}) #[[ATTR1]] // CHECK-DAG: attributes #[[ATTR0]] = {{{.*}}nomerge{{.*}}} diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6849,6 +6849,8 @@ break; default: llvm_unreachable("unknown trap intrinsic"); } + DAG.addNoMergeSiteInfo(DAG.getRoot().getNode(), + I.hasFnAttr(Attribute::NoMerge)); return; } TargetLowering::ArgListTy Args; @@ -6865,7 +6867,7 @@ 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 --- a/llvm/test/CodeGen/X86/nomerge.ll +++ b/llvm/test/CodeGen/X86/nomerge.ll @@ -22,7 +22,72 @@ declare dso_local void @bar() +define void @nomerge_trap(i32 %i) { +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) { +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) { +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" } ; CHECK-LABEL: foo: ; CHECK: # %bb.0: # %entry @@ -34,3 +99,33 @@ ; CHECK: callq bar ; CHECK: .LBB0_4: # %if.end3 ; CHECK: jmp bar # TAILCALL + +; CHECK-LABEL: nomerge_trap: +; CHECK: # %bb.0: # %entry +; CHECK: # %bb.1: # %entry +; CHECK: # %bb.2: # %if.then +; CHECK-NEXT: ud2 +; CHECK-NEXT: LBB1_3: # %if.then2 +; CHECK-NEXT: ud2 +; CHECK-NEXT: .LBB1_4: # %if.end3 +; CHECK-NEXT: ud2 + +; CHECK-LABEL: nomerge_debugtrap: +; CHECK: # %bb.0: # %entry +; CHECK: # %bb.1: # %entry +; CHECK: # %bb.2: # %if.then +; CHECK-NEXT: int3 +; CHECK-NEXT: LBB2_3: # %if.then2 +; CHECK-NEXT: int3 +; CHECK-NEXT: .LBB2_4: # %if.end3 +; CHECK-NEXT: int3 + +; 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: LBB3_3: # %if.then2 +; CHECK-NEXT: callq trap_func@PLT +; CHECK-NEXT: .LBB3_4: # %if.end3 +; CHECK-NEXT: callq trap_func@PLT