diff --git a/lib/Target/PowerPC/PPCCTRLoops.cpp b/lib/Target/PowerPC/PPCCTRLoops.cpp index 5d001fc0725..e8760dedea4 100644 --- a/lib/Target/PowerPC/PPCCTRLoops.cpp +++ b/lib/Target/PowerPC/PPCCTRLoops.cpp @@ -33,6 +33,7 @@ #include "llvm/Analysis/ScalarEvolutionExpander.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" @@ -148,6 +149,20 @@ bool PPCCTRLoops::mightUseCTR(const Triple &TT, BasicBlock *BB) { for (BasicBlock::iterator J = BB->begin(), JE = BB->end(); J != JE; ++J) { if (CallInst *CI = dyn_cast(J)) { + if (InlineAsm *IA = dyn_cast(CI->getCalledValue())) { + // Inline ASM is okay, unless it clobbers the ctr register. + InlineAsm::ConstraintInfoVector CIV = IA->ParseConstraints(); + for (unsigned i = 0, ie = CIV.size(); i < ie; ++i) { + InlineAsm::ConstraintInfo &C = CIV[i]; + if (C.Type != InlineAsm::isInput) + for (unsigned j = 0, je = C.Codes.size(); j < je; ++j) + if (StringRef(C.Codes[j]).equals_lower("{ctr}")) + return true; + } + + continue; + } + if (!TM) return true; const TargetLowering *TLI = TM->getTargetLowering(); diff --git a/test/CodeGen/PowerPC/ctrloop-asm.ll b/test/CodeGen/PowerPC/ctrloop-asm.ll new file mode 100644 index 00000000000..28afbf2babc --- /dev/null +++ b/test/CodeGen/PowerPC/ctrloop-asm.ll @@ -0,0 +1,38 @@ +target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32:64" +target triple = "powerpc64-unknown-freebsd10.0" +; RUN: llc < %s -march=ppc64 | FileCheck %s + +define void @test1(i32 %c) nounwind { +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ] + call void asm sideeffect "", "~{r5}"() nounwind + %inc = add nsw i32 %i.01, 1 + %exitcond = icmp eq i32 %inc, 2048 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +; CHECK: @test1 +; CHECK: mtctr +} + +define void @test2(i32 %c) nounwind { +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ] + call void asm sideeffect "", "~{ctr}"() nounwind + %inc = add nsw i32 %i.01, 1 + %exitcond = icmp eq i32 %inc, 2048 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +; CHECK: @test2 +; CHECK-NOT: mtctr +} +