summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHal Finkel <hfinkel@anl.gov>2013-05-18 09:20:39 +0000
committerHal Finkel <hfinkel@anl.gov>2013-05-18 09:20:39 +0000
commitbf0bc3b2a2e11ff7e79b881ca82324fe17919a97 (patch)
treed954a0523b7bedfa4720f460641dd06691eb9fcb
parent9f61e485e6c4a6763695ab399ff61567271836df (diff)
downloadllvm-bf0bc3b2a2e11ff7e79b881ca82324fe17919a97.tar.gz
llvm-bf0bc3b2a2e11ff7e79b881ca82324fe17919a97.tar.bz2
llvm-bf0bc3b2a2e11ff7e79b881ca82324fe17919a97.tar.xz
Check InlineAsm clobbers in PPCCTRLoops
We don't need to reject all inline asm as using the counter register (most does not). Only those that explicitly clobber the counter register need to prevent the transformation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182191 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/PowerPC/PPCCTRLoops.cpp15
-rw-r--r--test/CodeGen/PowerPC/ctrloop-asm.ll38
2 files changed, 53 insertions, 0 deletions
diff --git a/lib/Target/PowerPC/PPCCTRLoops.cpp b/lib/Target/PowerPC/PPCCTRLoops.cpp
index 5d001fc072..e8760dedea 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<CallInst>(J)) {
+ if (InlineAsm *IA = dyn_cast<InlineAsm>(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 0000000000..28afbf2bab
--- /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
+}
+