Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -9075,23 +9075,20 @@ continue; // Check for #1. - bool TryNext = false; + // Look for a real use, i.e. one use that is not a load / store op, or one + // that cannot be folded as addressing mode + bool TryNext = true; for (SDNode *Use : BasePtr.getNode()->uses()) { if (Use == Ptr.getNode()) continue; - // If all the uses are load / store addresses, then don't do the - // transformation. - if (Use->getOpcode() == ISD::ADD || Use->getOpcode() == ISD::SUB){ - bool RealUse = false; + // If one use is not a load / store address, then do the transformation. + if (Use->getOpcode() == ISD::ADD || Use->getOpcode() == ISD::SUB) { for (SDNode *UseUse : Use->uses()) { - if (!canFoldInAddressingMode(Use, UseUse, DAG, TLI)) - RealUse = true; - } - - if (!RealUse) { - TryNext = true; - break; + if (!canFoldInAddressingMode(Use, UseUse, DAG, TLI)) { + TryNext = false; + break; + } } } } Index: test/CodeGen/ARM/automod-test.ll =================================================================== --- test/CodeGen/ARM/automod-test.ll +++ test/CodeGen/ARM/automod-test.ll @@ -0,0 +1,66 @@ +; Test that checks that automod addressing mode is selected +; +; RUN: llc -O2 < %s -march=arm | FileCheck %s +; +; ====================================================== +; Without the fix, the generated code is the following : +; +; ldrh r3, [r2, #2] +; strh r3, [r1, #-2] +; ldrh r3, [r2] +; sub r2, r2, #6 +; strh r3, [r1] +; ldr r3, [r0], #48 +; add r1, r1, #6 +; cmp r3, #0 +; bne .LBB0_1 +; +; With the patch, post modifying addressing modes are selected : +; +; ldrh r3, [r2, #2] +; strh r3, [r1, #-2] +; ldrh r3, [r2], #-6 +; strh r3, [r1], #6 +; ldr r3, [r0], #48 +; cmp r3, #0 +; bne .LBB0_1 +; ====================================================== + +@input_tab64 = common global [32 x i16] zeroinitializer, align 2 +@output_tab64 = common global [32 x i16] zeroinitializer, align 2 + +; Function Attrs: nounwind +define void @compute(i32* nocapture readonly %IDX) #0 { +entry: + + %0 = load i32* %IDX, align 4 + %tobool14 = icmp eq i32 %0, 0 + br i1 %tobool14, label %for.end, label %for.body + +for.body: ; preds = %entry, %for.body + %i.015 = phi i32 [ %add8, %for.body ], [ 0, %entry ] + %sub = sub nsw i32 32, %i.015 + %sub1 = add nsw i32 %sub, -1 + %arrayidx2 = getelementptr inbounds [32 x i16]* @input_tab64, i32 0, i32 %sub1 + %1 = load i16* %arrayidx2, align 2 + %arrayidx3 = getelementptr inbounds [32 x i16]* @output_tab64, i32 0, i32 %i.015 + store i16 %1, i16* %arrayidx3, align 2 + %sub5 = add nsw i32 %sub, -2 + %arrayidx6 = getelementptr inbounds [32 x i16]* @input_tab64, i32 0, i32 %sub5 + %2 = load i16* %arrayidx6, align 2 + %add = add nsw i32 %i.015, 1 + %arrayidx7 = getelementptr inbounds [32 x i16]* @output_tab64, i32 0, i32 %add + store i16 %2, i16* %arrayidx7, align 2 + %add8 = add nsw i32 %i.015, 3 + %shl = shl i32 %add8, 2 + %arrayidx = getelementptr inbounds i32* %IDX, i32 %shl + %3 = load i32* %arrayidx, align 4 + %tobool = icmp eq i32 %3, 0 + br i1 %tobool, label %for.end, label %for.body + +; CHECK: ldrh r{{[0-9]+}}, [r{{[0-9]+}}], #-6 +; CHECK: strh r{{[0-9]+}}, [r{{[0-9]+}}], #6 + +for.end: ; preds = %for.body, %entry + ret void +}