I think the trouble we are having comes from the fact that we don't make it easy for IR producers (frontends or instrumentation passes) to do the right thing. If we make it easy (almost automatic), then maybe it will be more reasonable to declare in LangRef that function prototype mismatch is in fact UB.
Another developer suggested that the IRBuilder should take responsibility for setting the attributes on the call site, but I don't like the idea of IRBuilder::CreateCall inspecting the Callee argument with dyn_cast to decide its behavior.
This might be an infeasibly difficult ABI breaking change, but what if we had two overloads, one for direct calls, and one for indirect calls? Maybe we already have that in the current set of overloads:
CallInst *CreateCall(FunctionType *FTy, Value *Callee,
ArrayRef<Value *> Args = None, const Twine &Name = "",
MDNode *FPMathTag = nullptr);
CallInst *CreateCall(FunctionType *FTy, Value *Callee, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> OpBundles,
const Twine &Name = "", MDNode *FPMathTag = nullptr);
CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args = None,
const Twine &Name = "", MDNode *FPMathTag = nullptr);
CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> OpBundles,
const Twine &Name = "", MDNode *FPMathTag = nullptr);
Assuming the vast majority of callers use the FunctionCallee overload, which is implicitly constructible from a Function*, we could extend FunctionCallee to carry the calling convention and an attribute list. The CC and the attributes are actually part of clang::FunctionType, they just aren't part of llvm::FunctionType. FunctionCallee is sort of incomplete without them.
So, the task would be to add non-optional parameters to the FunctionType/Value overload (used for indirect calls) and then fix up all the call sites. Frontends that generate indirect calls would observe this as build breakage, not changes to generated code. Instrumentation passes would magically start doing the right thing without any source changes. This would also address the long-standing usability issue of calling conventions [1], which are optimized to unreachable if you forget to set the calling convention on the call site.
Having written this up, this seems like a good direction. Credit goes to the person that originally suggested the IRBuilder approach, I just had to think harder about it. :)