Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -10117,7 +10117,30 @@ if (LHS->getOpcode() == ARMISD::ADDE && isNullConstant(LHS->getOperand(0)) && isNullConstant(LHS->getOperand(1)) && isAllOnesConstant(RHS)) { - return DCI.CombineTo(N, SDValue(N, 0), LHS->getOperand(2)); + bool StillOK = true; + if (Subtarget->isThumb1Only()) { + // In Thumb1, if C is used by a node that is reachable from one of the + // users of N then we may end creating a DAG that requires copying CPSR + // to a GPR and we can't always do this. So in this case spend some + // time checking if it is OK to remove this (potentially) redundant + // operation. + SDNode *C = LHS->getOperand(2).getNode(); + for (const auto &Use : N->uses()) { + for (const auto &Op : Use->ops()) { + SDNode *OpN = Op.getNode(); + if (OpN != N && OpN->hasPredecessor(C)) { + StillOK = false; + break; + } + } + if (!StillOK) + break; + } + } + + if (StillOK) { + return DCI.CombineTo(N, SDValue(N, 0), LHS->getOperand(2)); + } } } Index: test/CodeGen/Thumb/pr35836.ll =================================================================== --- /dev/null +++ test/CodeGen/Thumb/pr35836.ll @@ -0,0 +1,51 @@ +; RUN: llc < %s | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" +target triple = "thumbv5e-none-linux-gnueabi" + +; Function Attrs: norecurse nounwind optsize +define void @f(i32,i32,i32,i32,i32* %x4p, i32* %x5p, i32* %x6p) { +if.end: + br label %while.body + +while.body: + %ll.0100 = phi i64 [ 0, %if.end ], [ %shr32, %while.body ] + %add = add nuw nsw i64 %ll.0100, 0 + %add3 = add nuw nsw i64 %add, 0 + %shr = lshr i64 %add3, 32 + %conv7 = zext i32 %0 to i64 + %conv9 = zext i32 %1 to i64 + %add10 = add nuw nsw i64 %conv9, %conv7 + %add11 = add nuw nsw i64 %add10, %shr + %shr14 = lshr i64 %add11, 32 + %conv16 = zext i32 %2 to i64 + %conv18 = zext i32 %3 to i64 + %add19 = add nuw nsw i64 %conv18, %conv16 + %add20 = add nuw nsw i64 %add19, %shr14 + %conv21 = trunc i64 %add20 to i32 + store i32 %conv21, i32* %x6p, align 4 + %shr23 = lshr i64 %add20, 32 + %x4 = load i32, i32* %x4p, align 4 + %conv25 = zext i32 %x4 to i64 + %x5 = load i32, i32* %x5p, align 4 + %conv27 = zext i32 %x5 to i64 + %add28 = add nuw nsw i64 %conv27, %conv25 + %add29 = add nuw nsw i64 %add28, %shr23 + %shr32 = lshr i64 %add29, 32 + br label %while.body + +; CHECK: adds +; CHECK: adcs +; CHECK: adds +; CHECK: adcs +; CHECK: adds +; CHECK: adcs +; CHECK: adcs +; CHECK: adds +; CHECK: adcs +; We need to preserve this seemingly redundant instruction otherwise copies +; CPSR <-> GPR would be emitted and we can't always do this in Thumb1. +; CHECK: subs {{r[0-9]+}}, {{r[0-9]+}}, #1 +; CHECK: adcs +; CHECK: adcs +}