diff --git a/llvm/test/tools/llvm-reduce/reduce-calling-convention.ll b/llvm/test/tools/llvm-reduce/reduce-calling-convention.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-reduce/reduce-calling-convention.ll @@ -0,0 +1,32 @@ +; Test that llvm-reduce can remove function calling conventions. +; +; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=function-data --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: FileCheck --check-prefix=CHECK-FINAL --implicit-check-not=fastcc %s < %t + +; CHECK-INTERESTINGNESS: declare +; CHECK-INTERESTINGNESS-SAME: void @f + +; CHECK-FINAL: declare void @f() + +declare void @f() + +; CHECK-INTERESTINGNESS: declare +; CHECK-INTERESTINGNESS-SAME: void @amdgpu + +; CHECK-FINAL: declare amdgpu_cs_chain void @amdgpu() + +declare amdgpu_cs_chain void @amdgpu() + +; CHECK-INTERESTINGNESS: declare +; CHECK-INTERESTINGNESS-SAME: void @g + +; CHECK-FINAL: declare void @g() + +declare fastcc void @g() + +; CHECK-FINAL: define void @callg() +; CHECK-FINAL: call void @g() +define void @callg() { + call fastcc void @g() + ret void +} diff --git a/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.cpp b/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.cpp --- a/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.cpp @@ -14,6 +14,7 @@ #include "ReduceFunctionBodies.h" #include "Delta.h" #include "Utils.h" +#include "llvm/IR/CallingConv.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Instructions.h" @@ -37,6 +38,18 @@ "Reducing Function Bodies"); } +static bool shouldReduceCallingConvention(Function &F) { + // The CCC is very lenient, so most calling conventions should be able to be + // changed to it. + switch (F.getCallingConv()) { + case CallingConv::C: + case CallingConv::AMDGPU_CS_Chain: + return false; + default: + return true; + } +} + static void reduceFunctionData(Oracle &O, ReducerWorkItem &WorkItem) { for (Function &F : WorkItem.getModule()) { if (F.hasPersonalityFn()) { @@ -54,6 +67,17 @@ if (F.hasPrologueData() && !O.shouldKeep()) F.setPrologueData(nullptr); + + if (shouldReduceCallingConvention(F) && !O.shouldKeep()) { + // Update callee calling conventions to avoid UB when possible. + for (Use &U : F.uses()) { + if (auto *CB = dyn_cast(U.getUser())) { + if (&CB->getCalledOperandUse() == &U) + CB->setCallingConv(CallingConv::C); + } + } + F.setCallingConv(CallingConv::C); + } } }