Index: lib/Target/ARM/ARMTargetTransformInfo.cpp =================================================================== --- lib/Target/ARM/ARMTargetTransformInfo.cpp +++ lib/Target/ARM/ARMTargetTransformInfo.cpp @@ -1054,14 +1054,17 @@ UP.Partial = true; UP.Runtime = true; UP.UpperBound = true; - UP.UnrollRemainder = true; + // Hopefully we'll be able to generate a low-overhead loop for both the + // unrolled loop and the remainder loop. + UP.UnrollRemainder = ST->hasLOB() ? false : true; UP.DefaultUnrollRuntimeCount = 4; UP.UnrollAndJam = true; UP.UnrollAndJamInnerLoopThreshold = 60; // Force unrolling small loops can be very useful because of the branch - // taken cost of the backedge. - if (Cost < 12) + // taken cost of the backedge, but generally shouldn't be required if we + // have low-overhead branches. + if (Cost < 12 && !ST->hasLOB()) UP.Force = true; } Index: test/Transforms/LoopUnroll/ARM/loop-unrolling.ll =================================================================== --- test/Transforms/LoopUnroll/ARM/loop-unrolling.ll +++ test/Transforms/LoopUnroll/ARM/loop-unrolling.ll @@ -1,9 +1,10 @@ -; RUN: opt -mtriple=armv7 -mcpu=cortex-a57 -loop-unroll -S %s -o - | FileCheck %s --check-prefix=CHECK-UNROLL-A -; RUN: opt -mtriple=thumbv7 -mcpu=cortex-a57 -loop-unroll -S %s -o - | FileCheck %s --check-prefix=CHECK-UNROLL-A -; RUN: opt -mtriple=thumbv7 -mcpu=cortex-a72 -loop-unroll -S %s -o - | FileCheck %s --check-prefix=CHECK-UNROLL-A -; RUN: opt -mtriple=thumbv8m -mcpu=cortex-m23 -loop-unroll -S %s -o - | FileCheck %s --check-prefix=CHECK-UNROLL-T1 -; RUN: opt -mtriple=thumbv8m.main -mcpu=cortex-m33 -loop-unroll -S %s -o - | FileCheck %s --check-prefix=CHECK-UNROLL-T2 -; RUN: opt -mtriple=thumbv7em -mcpu=cortex-m7 -loop-unroll -S %s -o - | FileCheck %s --check-prefix=CHECK-UNROLL-T2 +; RUN: opt -mtriple=armv7 -mcpu=cortex-a57 -loop-unroll -S %s -o - | FileCheck %s --check-prefix=CHECK-UNROLL-A --check-prefix=CHECK +; RUN: opt -mtriple=thumbv7 -mcpu=cortex-a57 -loop-unroll -S %s -o - | FileCheck %s --check-prefix=CHECK-UNROLL-A --check-prefix=CHECK +; RUN: opt -mtriple=thumbv7 -mcpu=cortex-a72 -loop-unroll -S %s -o - | FileCheck %s --check-prefix=CHECK-UNROLL-A --check-prefix=CHECK +; RUN: opt -mtriple=thumbv8m -mcpu=cortex-m23 -loop-unroll -S %s -o - | FileCheck %s --check-prefix=CHECK-UNROLL-T1 --check-prefix=CHECK +; RUN: opt -mtriple=thumbv8m.main -mcpu=cortex-m33 -loop-unroll -S %s -o - | FileCheck %s --check-prefix=CHECK-UNROLL-T2 --check-prefix=CHECK +; RUN: opt -mtriple=thumbv7em -mcpu=cortex-m7 -loop-unroll -S %s -o - | FileCheck %s --check-prefix=CHECK-UNROLL-T2 --check-prefix=CHECK +; RUN: opt -mtriple=thumbv8.1m.main -loop-unroll -S %s -o - | FileCheck %s --check-prefix=CHECK-UNROLL-LOB --check-prefix=CHECK ; CHECK-LABEL: partial define arm_aapcs_vfpcc void @partial(i32* nocapture %C, i32* nocapture readonly %A, i32* nocapture readonly %B) local_unnamed_addr #0 { @@ -44,6 +45,26 @@ ; CHECK-UNROLL-T2: [[CMP:%[a-z.0-9]+]] = icmp eq i32 [[IV16]], 1024 ; CHECK-UNROLL-T2: br i1 [[CMP]], label [[END:%[a-z.]+]], label %for.body +; CHECK-UNROLL-LOB: [[IV0:%[a-z.0-9]+]] = phi i32 [ 0, %entry ], [ [[IV16:%[a-z.0-9]+]], %for.body ] +; CHECK-UNROLL-LOB: [[IV1:%[a-z.0-9]+]] = add nuw nsw i32 [[IV0]], 1 +; CHECK-UNROLL-LOB: [[IV2:%[a-z.0-9]+]] = add nuw nsw i32 [[IV1]], 1 +; CHECK-UNROLL-LOB: [[IV3:%[a-z.0-9]+]] = add nuw nsw i32 [[IV2]], 1 +; CHECK-UNROLL-LOB: [[IV4:%[a-z.0-9]+]] = add nuw nsw i32 [[IV3]], 1 +; CHECK-UNROLL-LOB: [[IV5:%[a-z.0-9]+]] = add nuw nsw i32 [[IV4]], 1 +; CHECK-UNROLL-LOB: [[IV6:%[a-z.0-9]+]] = add nuw nsw i32 [[IV5]], 1 +; CHECK-UNROLL-LOB: [[IV7:%[a-z.0-9]+]] = add nuw nsw i32 [[IV6]], 1 +; CHECK-UNROLL-LOB: [[IV8:%[a-z.0-9]+]] = add nuw nsw i32 [[IV7]], 1 +; CHECK-UNROLL-LOB: [[IV9:%[a-z.0-9]+]] = add nuw nsw i32 [[IV8]], 1 +; CHECK-UNROLL-LOB: [[IV10:%[a-z.0-9]+]] = add nuw nsw i32 [[IV9]], 1 +; CHECK-UNROLL-LOB: [[IV11:%[a-z.0-9]+]] = add nuw nsw i32 [[IV10]], 1 +; CHECK-UNROLL-LOB: [[IV12:%[a-z.0-9]+]] = add nuw nsw i32 [[IV11]], 1 +; CHECK-UNROLL-LOB: [[IV13:%[a-z.0-9]+]] = add nuw nsw i32 [[IV12]], 1 +; CHECK-UNROLL-LOB: [[IV14:%[a-z.0-9]+]] = add nuw nsw i32 [[IV13]], 1 +; CHECK-UNROLL-LOB: [[IV15:%[a-z.0-9]+]] = add nuw nsw i32 [[IV14]], 1 +; CHECK-UNROLL-LOB: [[IV16]] = add nuw nsw i32 [[IV15]], 1 +; CHECK-UNROLL-LOB: [[CMP:%[a-z.0-9]+]] = icmp eq i32 [[IV16]], 1024 +; CHECK-UNROLL-LOB: br i1 [[CMP]], label [[END:%[a-z.]+]], label %for.body + %i.08 = phi i32 [ 0, %entry ], [ %inc, %for.body ] %arrayidx = getelementptr inbounds i32, i32* %A, i32 %i.08 %0 = load i32, i32* %arrayidx, align 4 @@ -89,6 +110,16 @@ ; CHECK-UNROLL-T2: for.body.epil.1: ; CHECK-UNROLL-T2: for.body.epil.2: +; CHECK-UNROLL-LOB: [[IV0:%[a-z.0-9]+]] = phi i32 [ 0, [[PRE:%[a-z.0-9]+]] ], [ [[IV4:%[a-z.0-9]+]], %for.body ] +; CHECK-UNROLL-LOB: [[IV1:%[a-z.0-9]+]] = add nuw nsw i32 [[IV0]], 1 +; CHECK-UNROLL-LOB: [[IV2:%[a-z.0-9]+]] = add nuw nsw i32 [[IV1]], 1 +; CHECK-UNROLL-LOB: [[IV3:%[a-z.0-9]+]] = add nuw nsw i32 [[IV2]], 1 +; CHECK-UNROLL-LOB: [[IV4]] = add nuw i32 [[IV3]], 1 +; CHECK-UNROLL-LOB: br + +; CHECK-UNROLL-LOB: for.body.epil: +; CHECK-UNROLL-LOB-NOT: for.body.epil.1: + %i.09 = phi i32 [ %inc, %for.body ], [ 0, %entry ] %arrayidx = getelementptr inbounds i32, i32* %A, i32 %i.09 %0 = load i32, i32* %arrayidx, align 4 @@ -140,6 +171,15 @@ ; CHECK-UNROLL-T2: for.body4.epil.1: ; CHECK-UNROLL-T2: for.body4.epil.2: +; CHECK-UNROLL-LOB: for.body4.epil: +; CHECK-UNROLL-LOB: [[IV0:%[a-z.0-9]+]] = phi i32 [ 0, [[PRE:%[a-z0-9.]+]] ], [ [[IV4:%[a-z.0-9]+]], %for.body4 ] +; CHECK-UNROLL-LOB: [[IV1:%[a-z.0-9]+]] = add nuw nsw i32 [[IV0]], 1 +; CHECK-UNROLL-LOB: [[IV2:%[a-z.0-9]+]] = add nuw nsw i32 [[IV1]], 1 +; CHECK-UNROLL-LOB: [[IV3:%[a-z.0-9]+]] = add nuw nsw i32 [[IV2]], 1 +; CHECK-UNROLL-LOB: [[IV4]] = add nuw i32 [[IV3]], 1 +; CHECK-UNROLL-LOB: br +; CHECK-UNROLL-LOB-NOT: for.body4.epil.1: + %w.024 = phi i32 [ 0, %for.body4.lr.ph ], [ %inc, %for.body4 ] %add = add i32 %w.024, %mul %arrayidx = getelementptr inbounds i16, i16* %A, i32 %add @@ -207,6 +247,11 @@ ; CHECK-UNROLL-T1: br i1 %tobool ; CHECK-UNROLL-T1-NOT: load +; CHECK-UNROLL-LOB: %n.addr.04 = phi %struct.Node* [ %1, %while.body ], [ %n, %while.body.preheader ] +; CHECK-UNROLL-LOB: %tobool = icmp eq %struct.Node* %1, null +; CHECK-UNROLL-LOB: br i1 %tobool +; CHECK-UNROLL-LOB-NOT: load + ; CHECK-UNROLL-T2: [[CMP0:%[a-z.0-9]+]] = icmp eq %struct.Node* [[VAR0:%[a-z.0-9]+]], null ; CHECK-UNROLL-T2: br i1 [[CMP0]], label [[END:%[a-z.0-9]+]] ; CHECK-UNROLL-T2: [[CMP1:%[a-z.0-9]+]] = icmp eq %struct.Node* [[VAR1:%[a-z.0-9]+]], null