summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaleem Abdulrasool <compnerd@compnerd.org>2014-08-10 22:20:37 +0000
committerSaleem Abdulrasool <compnerd@compnerd.org>2014-08-10 22:20:37 +0000
commited8885b40273b84c2e1f946f1ad0cb484c737821 (patch)
treeee18d216967f77153b948db7af730d91808f6129
parent037e75bf3c91d937a3f827c8dcc33f493bb0ef7c (diff)
downloadbcm5719-llvm-ed8885b40273b84c2e1f946f1ad0cb484c737821.tar.gz
bcm5719-llvm-ed8885b40273b84c2e1f946f1ad0cb484c737821.zip
ARM: correct isPredicable for MULS in ThHUMB mode
The ARM ARM states that CPSR may not be updated by a MUL in thumb mode. Due to an ordering of Thumb 2 Size Reduction and If Conversion, we would end up generating a THUMB MULS inside an IT block. The If Conversion pass uses the TTI isPredicable method to ensure that it can transform a Basic Block. However, because we only check for IT handling on Thumb2 functions, we may miss some cases. Even then, it only validates that the CPSR is not *live* rather than it is not accessed. This corrects the handling for that particular case since the same restriction does not hold on the vast majority of the instructions. This does prevent the IfConversion optimization from kicking in in certain cases, but generating correct code is more valuable. Addresses PR20555. llvm-svn: 215328
-rw-r--r--llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp14
-rw-r--r--llvm/test/CodeGen/ARM/2014-08-04-muls-it.ll25
2 files changed, 39 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
index d78a26fee0f..bee5bfd7b2e 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
@@ -518,6 +518,13 @@ bool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI,
return Found;
}
+static bool isCPSRDefined(const MachineInstr *MI) {
+ for (const auto &MO : MI->operands())
+ if (MO.isReg() && MO.getReg() == ARM::CPSR && (MO.isDef() || !MO.isDead()))
+ return true;
+ return false;
+}
+
/// isPredicable - Return true if the specified instruction can be predicated.
/// By default, this returns true for every instruction with a
/// PredicateOperand.
@@ -525,6 +532,13 @@ bool ARMBaseInstrInfo::isPredicable(MachineInstr *MI) const {
if (!MI->isPredicable())
return false;
+ // The ARM Architecture Reference Manual states that the CPSR may only be
+ // accessed by MUL in Thumb mode if it is outside an IT block. Thus, if CPSR
+ // is defined (or clobbered) by this instruction, it is not predicable.
+ if (MI->getOpcode() == ARM::tMUL || MI->getOpcode() == ARM::t2MUL)
+ if (isCPSRDefined(MI))
+ return false;
+
ARMFunctionInfo *AFI =
MI->getParent()->getParent()->getInfo<ARMFunctionInfo>();
diff --git a/llvm/test/CodeGen/ARM/2014-08-04-muls-it.ll b/llvm/test/CodeGen/ARM/2014-08-04-muls-it.ll
new file mode 100644
index 00000000000..4636bff880a
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/2014-08-04-muls-it.ll
@@ -0,0 +1,25 @@
+; RUN: llc -mtriple thumbv7-eabi -arm-restrict-it -filetype asm -o - %s \
+; RUN: | FileCheck %s
+
+define arm_aapcscc i32 @function(i32 %i, i32 %j) {
+entry:
+ %cmp = icmp eq i32 %i, %j
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ %mul = mul nsw i32 %i, %i
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ %i.addr.0 = phi i32 [ %mul, %if.then ], [ %i, %entry ]
+ ret i32 %i.addr.0
+}
+
+; CHECK-LABEL: function
+; CHECK: cmp r0, r1
+; CHECK: bne [[LABEL:[.*]]]
+; CHECK-NOT: mulseq r0, r0, r0
+; CHECK: [[LABEL]]
+; CHECK: muls r0, r0, r0
+; CHECK: bx lr
+
OpenPOWER on IntegriCloud