summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp')
-rw-r--r--llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp14
1 files changed, 14 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>();
OpenPOWER on IntegriCloud