[llvm] r203488 - For functions with ARM target specific calling convention, when simplify-libcall

Evan Cheng evan.cheng at apple.com
Mon Mar 10 13:49:46 PDT 2014


Author: evancheng
Date: Mon Mar 10 15:49:45 2014
New Revision: 203488

URL: http://llvm.org/viewvc/llvm-project?rev=203488&view=rev
Log:
For functions with ARM target specific calling convention, when simplify-libcall
optimize a call to a llvm intrinsic to something that invovles a call to a C
library call, make sure it sets the right calling convention on the call.

e.g.
extern double pow(double, double);
double t(double x) {
  return pow(10, x);
}

Compiles to something like this for AAPCS-VFP:
define arm_aapcs_vfpcc double @t(double %x) #0 {
entry:
  %0 = call double @llvm.pow.f64(double 1.000000e+01, double %x)
  ret double %0
}

declare double @llvm.pow.f64(double, double) #1

Simplify libcall (part of instcombine) will turn the above into:
define arm_aapcs_vfpcc double @t(double %x) #0 {
entry:
  %__exp10 = call double @__exp10(double %x) #1
  ret double %__exp10
}

declare double @__exp10(double)

The pre-instcombine code works because calls to LLVM builtins are special.
Instruction selection will chose the right calling convention for the call.
However, the code after instcombine is wrong. The call to __exp10 will use
the C calling convention.

I can think of 3 options to fix this.

1. Make "C" calling convention just work since the target should know what CC
   is being used.

   This doesn't work because each function can use different CC with the "pcs"
   attribute.

2. Have Clang add the right CC keyword on the calls to LLVM builtin.

   This will work but it doesn't match the LLVM IR specification which states
   these are "Standard C Library Intrinsics".

3. Fix simplify libcall so the resulting calls to the C routines will have the
   proper CC keyword. e.g.
   %__exp10 = call arm_aapcs_vfpcc double @__exp10(double %x) #1

   This works and is the solution I implemented here.

Both solutions #2 and #3 would work. After carefully considering the pros and
cons, I decided to implement #3 for the following reasons.

1. It doesn't change the "spec" of the intrinsics.
2. It's a self-contained fix.

There are a couple of potential downsides.
1. There could be other places in the optimizer that is broken in the same way
   that's not addressed by this.
2. There could be other calling conventions that need to be propagated by
   simplify-libcall that's not handled.

But for now, this is the fix that I'm most comfortable with.

Added:
    llvm/trunk/test/Transforms/InstCombine/simplify-libcalls-aapcs.ll
Modified:
    llvm/trunk/include/llvm/IR/CallingConv.h
    llvm/trunk/lib/IR/Function.cpp
    llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp

Modified: llvm/trunk/include/llvm/IR/CallingConv.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CallingConv.h?rev=203488&r1=203487&r2=203488&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/CallingConv.h (original)
+++ llvm/trunk/include/llvm/IR/CallingConv.h Mon Mar 10 15:49:45 2014
@@ -145,6 +145,10 @@ namespace CallingConv {
     X86_CDeclMethod = 80
 
   };
+
+  /// isARMTargetCC - Return true if the specific calling convention is one of
+  /// ARM target specific calling convention.
+  bool isARMTargetCC(ID id);
 } // End CallingConv namespace
 
 } // End llvm namespace

Modified: llvm/trunk/lib/IR/Function.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Function.cpp?rev=203488&r1=203487&r2=203488&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Function.cpp (original)
+++ llvm/trunk/lib/IR/Function.cpp Mon Mar 10 15:49:45 2014
@@ -779,3 +779,11 @@ void Function::setPrefixData(Constant *P
   }
   setValueSubclassData(SCData);
 }
+
+
+/// isARMTargetCC - Return true if the specific calling convention is one of
+/// ARM target specific calling convention.
+/// There isn't a CallingConv.cpp so we are adding this utility routine here.
+bool CallingConv::isARMTargetCC(ID id) {
+  return id == ARM_APCS || id == ARM_AAPCS || id == ARM_AAPCS_VFP;
+}

Modified: llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp?rev=203488&r1=203487&r2=203488&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp Mon Mar 10 15:49:45 2014
@@ -37,7 +37,8 @@ Value *llvm::EmitStrLen(Value *Ptr, IRBu
   if (!TLI->has(LibFunc::strlen))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   AttributeSet AS[2];
   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
   Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind };
@@ -52,8 +53,18 @@ Value *llvm::EmitStrLen(Value *Ptr, IRBu
                                             B.getInt8PtrTy(),
                                             NULL);
   CallInst *CI = B.CreateCall(StrLen, CastToCStr(Ptr, B), "strlen");
-  if (const Function *F = dyn_cast<Function>(StrLen->stripPointerCasts()))
-    CI->setCallingConv(F->getCallingConv());
+  if (Function *F = dyn_cast<Function>(StrLen->stripPointerCasts())) {
+    CallingConv::ID CC = F->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      F->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
 
   return CI;
 }
@@ -66,7 +77,8 @@ Value *llvm::EmitStrNLen(Value *Ptr, Val
   if (!TLI->has(LibFunc::strnlen))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   AttributeSet AS[2];
   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
   Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind };
@@ -82,8 +94,18 @@ Value *llvm::EmitStrNLen(Value *Ptr, Val
                                              TD->getIntPtrType(Context),
                                              NULL);
   CallInst *CI = B.CreateCall2(StrNLen, CastToCStr(Ptr, B), MaxLen, "strnlen");
-  if (const Function *F = dyn_cast<Function>(StrNLen->stripPointerCasts()))
-    CI->setCallingConv(F->getCallingConv());
+  if (Function *F = dyn_cast<Function>(StrNLen->stripPointerCasts())) {
+    CallingConv::ID CC = F->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      F->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
 
   return CI;
 }
@@ -96,7 +118,8 @@ Value *llvm::EmitStrChr(Value *Ptr, char
   if (!TLI->has(LibFunc::strchr))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind };
   AttributeSet AS =
     AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
@@ -110,8 +133,19 @@ Value *llvm::EmitStrChr(Value *Ptr, char
                                             I8Ptr, I8Ptr, I32Ty, NULL);
   CallInst *CI = B.CreateCall2(StrChr, CastToCStr(Ptr, B),
                                ConstantInt::get(I32Ty, C), "strchr");
-  if (const Function *F = dyn_cast<Function>(StrChr->stripPointerCasts()))
-    CI->setCallingConv(F->getCallingConv());
+  if (Function *F = dyn_cast<Function>(StrChr->stripPointerCasts())) {
+    CallingConv::ID CC = F->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      F->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
+
   return CI;
 }
 
@@ -122,7 +156,8 @@ Value *llvm::EmitStrNCmp(Value *Ptr1, Va
   if (!TLI->has(LibFunc::strncmp))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   AttributeSet AS[3];
   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
   AS[1] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
@@ -141,8 +176,18 @@ Value *llvm::EmitStrNCmp(Value *Ptr1, Va
   CallInst *CI = B.CreateCall3(StrNCmp, CastToCStr(Ptr1, B),
                                CastToCStr(Ptr2, B), Len, "strncmp");
 
-  if (const Function *F = dyn_cast<Function>(StrNCmp->stripPointerCasts()))
-    CI->setCallingConv(F->getCallingConv());
+  if (Function *F = dyn_cast<Function>(StrNCmp->stripPointerCasts())) {
+    CallingConv::ID CC = F->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      F->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
 
   return CI;
 }
@@ -155,7 +200,8 @@ Value *llvm::EmitStrCpy(Value *Dst, Valu
   if (!TLI->has(LibFunc::strcpy))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   AttributeSet AS[2];
   AS[0] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
   AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
@@ -166,8 +212,19 @@ Value *llvm::EmitStrCpy(Value *Dst, Valu
                                          I8Ptr, I8Ptr, I8Ptr, NULL);
   CallInst *CI = B.CreateCall2(StrCpy, CastToCStr(Dst, B), CastToCStr(Src, B),
                                Name);
-  if (const Function *F = dyn_cast<Function>(StrCpy->stripPointerCasts()))
-    CI->setCallingConv(F->getCallingConv());
+  if (Function *F = dyn_cast<Function>(StrCpy->stripPointerCasts())) {
+    CallingConv::ID CC = F->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      F->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
+
   return CI;
 }
 
@@ -179,7 +236,8 @@ Value *llvm::EmitStrNCpy(Value *Dst, Val
   if (!TLI->has(LibFunc::strncpy))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   AttributeSet AS[2];
   AS[0] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
   AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
@@ -192,8 +250,19 @@ Value *llvm::EmitStrNCpy(Value *Dst, Val
                                           Len->getType(), NULL);
   CallInst *CI = B.CreateCall3(StrNCpy, CastToCStr(Dst, B), CastToCStr(Src, B),
                                Len, "strncpy");
-  if (const Function *F = dyn_cast<Function>(StrNCpy->stripPointerCasts()))
-    CI->setCallingConv(F->getCallingConv());
+  if (Function *F = dyn_cast<Function>(StrNCpy->stripPointerCasts())) {
+    CallingConv::ID CC = F->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      F->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
+
   return CI;
 }
 
@@ -206,7 +275,8 @@ Value *llvm::EmitMemCpyChk(Value *Dst, V
   if (!TLI->has(LibFunc::memcpy_chk))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   AttributeSet AS;
   AS = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
                          Attribute::NoUnwind);
@@ -221,8 +291,19 @@ Value *llvm::EmitMemCpyChk(Value *Dst, V
   Dst = CastToCStr(Dst, B);
   Src = CastToCStr(Src, B);
   CallInst *CI = B.CreateCall4(MemCpy, Dst, Src, Len, ObjSize);
-  if (const Function *F = dyn_cast<Function>(MemCpy->stripPointerCasts()))
-    CI->setCallingConv(F->getCallingConv());
+  if (Function *F = dyn_cast<Function>(MemCpy->stripPointerCasts())) {
+    CallingConv::ID CC = F->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      F->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
+
   return CI;
 }
 
@@ -234,7 +315,8 @@ Value *llvm::EmitMemChr(Value *Ptr, Valu
   if (!TLI->has(LibFunc::memchr))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   AttributeSet AS;
   Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind };
   AS = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
@@ -249,8 +331,18 @@ Value *llvm::EmitMemChr(Value *Ptr, Valu
                                          NULL);
   CallInst *CI = B.CreateCall3(MemChr, CastToCStr(Ptr, B), Val, Len, "memchr");
 
-  if (const Function *F = dyn_cast<Function>(MemChr->stripPointerCasts()))
-    CI->setCallingConv(F->getCallingConv());
+  if (Function *F = dyn_cast<Function>(MemChr->stripPointerCasts())) {
+    CallingConv::ID CC = F->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      F->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
 
   return CI;
 }
@@ -262,7 +354,8 @@ Value *llvm::EmitMemCmp(Value *Ptr1, Val
   if (!TLI->has(LibFunc::memcmp))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   AttributeSet AS[3];
   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
   AS[1] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
@@ -280,8 +373,18 @@ Value *llvm::EmitMemCmp(Value *Ptr1, Val
   CallInst *CI = B.CreateCall3(MemCmp, CastToCStr(Ptr1, B), CastToCStr(Ptr2, B),
                                Len, "memcmp");
 
-  if (const Function *F = dyn_cast<Function>(MemCmp->stripPointerCasts()))
-    CI->setCallingConv(F->getCallingConv());
+  if (Function *F = dyn_cast<Function>(MemCmp->stripPointerCasts())) {
+    CallingConv::ID CC = F->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      F->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
 
   return CI;
 }
@@ -310,13 +413,24 @@ Value *llvm::EmitUnaryFloatFnCall(Value
   SmallString<20> NameBuffer;
   AppendTypeSuffix(Op, Name, NameBuffer);   
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   Value *Callee = M->getOrInsertFunction(Name, Op->getType(),
                                          Op->getType(), NULL);
   CallInst *CI = B.CreateCall(Callee, Op, Name);
   CI->setAttributes(Attrs);
-  if (const Function *F = dyn_cast<Function>(Callee->stripPointerCasts()))
-    CI->setCallingConv(F->getCallingConv());
+  if (Function *F = dyn_cast<Function>(Callee->stripPointerCasts())) {
+    CallingConv::ID CC = F->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      F->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
 
   return CI;
 }
@@ -331,13 +445,24 @@ Value *llvm::EmitBinaryFloatFnCall(Value
   SmallString<20> NameBuffer;
   AppendTypeSuffix(Op1, Name, NameBuffer);   
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   Value *Callee = M->getOrInsertFunction(Name, Op1->getType(),
                                          Op1->getType(), Op2->getType(), NULL);
   CallInst *CI = B.CreateCall2(Callee, Op1, Op2, Name);
   CI->setAttributes(Attrs);
-  if (const Function *F = dyn_cast<Function>(Callee->stripPointerCasts()))
-    CI->setCallingConv(F->getCallingConv());
+  if (Function *F = dyn_cast<Function>(Callee->stripPointerCasts())) {
+    CallingConv::ID CC = F->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      F->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
 
   return CI;
 }
@@ -349,7 +474,8 @@ Value *llvm::EmitPutChar(Value *Char, IR
   if (!TLI->has(LibFunc::putchar))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   Value *PutChar = M->getOrInsertFunction("putchar", B.getInt32Ty(),
                                           B.getInt32Ty(), NULL);
   CallInst *CI = B.CreateCall(PutChar,
@@ -359,8 +485,19 @@ Value *llvm::EmitPutChar(Value *Char, IR
                               "chari"),
                               "putchar");
 
-  if (const Function *F = dyn_cast<Function>(PutChar->stripPointerCasts()))
-    CI->setCallingConv(F->getCallingConv());
+  if (Function *F = dyn_cast<Function>(PutChar->stripPointerCasts())) {
+    CallingConv::ID CC = F->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      F->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
+
   return CI;
 }
 
@@ -371,7 +508,8 @@ Value *llvm::EmitPutS(Value *Str, IRBuil
   if (!TLI->has(LibFunc::puts))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   AttributeSet AS[2];
   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
   AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
@@ -383,8 +521,19 @@ Value *llvm::EmitPutS(Value *Str, IRBuil
                                        B.getInt8PtrTy(),
                                        NULL);
   CallInst *CI = B.CreateCall(PutS, CastToCStr(Str, B), "puts");
-  if (const Function *F = dyn_cast<Function>(PutS->stripPointerCasts()))
-    CI->setCallingConv(F->getCallingConv());
+  if (Function *F = dyn_cast<Function>(PutS->stripPointerCasts())) {
+    CallingConv::ID CC = F->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      F->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
+
   return CI;
 }
 
@@ -395,7 +544,8 @@ Value *llvm::EmitFPutC(Value *Char, Valu
   if (!TLI->has(LibFunc::fputc))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   AttributeSet AS[2];
   AS[0] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
   AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
@@ -416,8 +566,19 @@ Value *llvm::EmitFPutC(Value *Char, Valu
                          "chari");
   CallInst *CI = B.CreateCall2(F, Char, File, "fputc");
 
-  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
-    CI->setCallingConv(Fn->getCallingConv());
+  if (Function *Fn = dyn_cast<Function>(F->stripPointerCasts())) {
+    CallingConv::ID CC = Fn->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      Fn->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
+
   return CI;
 }
 
@@ -428,7 +589,8 @@ Value *llvm::EmitFPutS(Value *Str, Value
   if (!TLI->has(LibFunc::fputs))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   AttributeSet AS[3];
   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
   AS[1] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
@@ -448,8 +610,19 @@ Value *llvm::EmitFPutS(Value *Str, Value
                                File->getType(), NULL);
   CallInst *CI = B.CreateCall2(F, CastToCStr(Str, B), File, "fputs");
 
-  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
-    CI->setCallingConv(Fn->getCallingConv());
+  if (Function *Fn = dyn_cast<Function>(F->stripPointerCasts())) {
+    CallingConv::ID CC = Fn->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      Fn->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
+
   return CI;
 }
 
@@ -461,7 +634,8 @@ Value *llvm::EmitFWrite(Value *Ptr, Valu
   if (!TLI->has(LibFunc::fwrite))
     return 0;
 
-  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Function *CallerF = B.GetInsertBlock()->getParent();
+  Module *M = CallerF->getParent();
   AttributeSet AS[3];
   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
   AS[1] = AttributeSet::get(M->getContext(), 4, Attribute::NoCapture);
@@ -487,8 +661,19 @@ Value *llvm::EmitFWrite(Value *Ptr, Valu
   CallInst *CI = B.CreateCall4(F, CastToCStr(Ptr, B), Size,
                         ConstantInt::get(TD->getIntPtrType(Context), 1), File);
 
-  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
-    CI->setCallingConv(Fn->getCallingConv());
+  if (Function *Fn = dyn_cast<Function>(F->stripPointerCasts())) {
+    CallingConv::ID CC = Fn->getCallingConv();
+    CallingConv::ID CallerCC = CallerF->getCallingConv();
+    if (CC == CallingConv::C && CallingConv::isARMTargetCC(CallerCC)) {
+      // If caller is using ARM target specific CC such as AAPCS-VFP,
+      // make sure the call uses it or it would introduce a calling
+      // convention mismatch.
+      CI->setCallingConv(CallerCC);
+      Fn->setCallingConv(CallerCC);
+    } else
+      CI->setCallingConv(CC);
+  }
+
   return CI;
 }
 

Added: llvm/trunk/test/Transforms/InstCombine/simplify-libcalls-aapcs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/simplify-libcalls-aapcs.ll?rev=203488&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/simplify-libcalls-aapcs.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/simplify-libcalls-aapcs.ll Mon Mar 10 15:49:45 2014
@@ -0,0 +1,23 @@
+; RUN: opt -S < %s -instcombine | FileCheck %s
+
+; When simplify-libcall change an intrinsic call to a call to a library
+; routine, it needs to set the proper calling convention for callers
+; which use ARM target specific calling conventions.
+; rdar://16261856
+
+target triple = "thumbv7-apple-ios7"
+
+; Function Attrs: nounwind ssp
+define arm_aapcs_vfpcc double @t(double %x) #0 {
+entry:
+; CHECK-LABEL: @t
+; CHECK: call arm_aapcs_vfpcc double @__exp10
+  %0 = call double @llvm.pow.f64(double 1.000000e+01, double %x)
+  ret double %0
+}
+
+; Function Attrs: nounwind readnone
+declare double @llvm.pow.f64(double, double) #1
+
+attributes #0 = { nounwind ssp }
+attributes #1 = { nounwind readnone }





More information about the llvm-commits mailing list