137 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes="default<O3>" -rotation-max-header-size=0 -S < %s | FileCheck %s --check-prefix=HOIST3; RUN: opt -passes="default<O3>" -rotation-max-header-size=1 -S < %s | FileCheck %s --check-prefix=HOIST4; RUN: opt -passes="default<O3>" -rotation-max-header-size=2 -S < %s | FileCheck %s --check-prefix=ROTATE5; RUN: opt -passes="default<O3>" -rotation-max-header-size=3 -S < %s | FileCheck %s --check-prefix=ROTATE6 7; This example is produced from a very basic C code:8;9; void f0();10; void f1();11; void f2();12;13; void loop(int width) {14; if(width < 1)15; return;16; for(int i = 0; i < width - 1; ++i) {17; f0();18; f1();19; }20; f0();21; f2();22; }23 24; We have a choice here. We can either25; * hoist the f0() call into loop header,26; * which potentially makes loop rotation unprofitable since loop header might27; have grown above certain threshold, and such unrotated loops will be28; ignored by LoopVectorizer, preventing vectorization29; * or loop rotation will succeed, resulting in some weird PHIs that will also30; harm vectorization31; * or not hoist f0() call before performing loop rotation,32; at the cost of potential code bloat and/or potentially successfully rotating33; the loops, vectorizing them at the cost of compile time.34 35target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"36 37declare void @f0()38declare void @f1()39declare void @f2()40 41declare void @llvm.lifetime.start.p0(ptr nocapture)42declare void @llvm.lifetime.end.p0(ptr nocapture)43 44define void @_Z4loopi(i32 %width) {45; HOIST-LABEL: @_Z4loopi(46; HOIST-NEXT: entry:47; HOIST-NEXT: [[CMP:%.*]] = icmp slt i32 [[WIDTH:%.*]], 148; HOIST-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[FOR_COND_PREHEADER:%.*]]49; HOIST: for.cond.preheader:50; HOIST-NEXT: [[SUB:%.*]] = add nsw i32 [[WIDTH]], -151; HOIST-NEXT: br label [[FOR_COND:%.*]]52; HOIST: for.cond:53; HOIST-NEXT: [[I_0:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[FOR_COND_PREHEADER]] ]54; HOIST-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[I_0]], [[SUB]]55; HOIST-NEXT: tail call void @f0()56; HOIST-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]57; HOIST: for.cond.cleanup:58; HOIST-NEXT: tail call void @f2()59; HOIST-NEXT: br label [[RETURN]]60; HOIST: for.body:61; HOIST-NEXT: tail call void @f1()62; HOIST-NEXT: [[INC]] = add nuw i32 [[I_0]], 163; HOIST-NEXT: br label [[FOR_COND]]64; HOIST: return:65; HOIST-NEXT: ret void66;67; ROTATE-LABEL: @_Z4loopi(68; ROTATE-NEXT: entry:69; ROTATE-NEXT: [[CMP:%.*]] = icmp slt i32 [[WIDTH:%.*]], 170; ROTATE-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[FOR_COND_PREHEADER:%.*]]71; ROTATE: for.cond.preheader:72; ROTATE-NEXT: [[CMP13_NOT:%.*]] = icmp eq i32 [[WIDTH]], 173; ROTATE-NEXT: br i1 [[CMP13_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PREHEADER:%.*]]74; ROTATE: for.body.preheader:75; ROTATE-NEXT: [[TMP0:%.*]] = add nsw i32 [[WIDTH]], -276; ROTATE-NEXT: br label [[FOR_BODY:%.*]]77; ROTATE: for.cond.cleanup:78; ROTATE-NEXT: tail call void @f0()79; ROTATE-NEXT: tail call void @f2()80; ROTATE-NEXT: br label [[RETURN]]81; ROTATE: for.body:82; ROTATE-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]83; ROTATE-NEXT: tail call void @f0()84; ROTATE-NEXT: tail call void @f1()85; ROTATE-NEXT: [[INC]] = add nuw nsw i32 [[I_04]], 186; ROTATE-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[I_04]], [[TMP0]]87; ROTATE-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]]88; ROTATE: return:89; ROTATE-NEXT: ret void90;91entry:92 %width.addr = alloca i32, align 493 %i = alloca i32, align 494 store i32 %width, ptr %width.addr, align 495 %i1 = load i32, ptr %width.addr, align 496 %cmp = icmp slt i32 %i1, 197 br i1 %cmp, label %if.then, label %if.end98 99if.then:100 br label %return101 102if.end:103 call void @llvm.lifetime.start.p0(ptr %i)104 store i32 0, ptr %i, align 4105 br label %for.cond106 107for.cond:108 %i3 = load i32, ptr %i, align 4109 %i4 = load i32, ptr %width.addr, align 4110 %sub = sub nsw i32 %i4, 1111 %cmp1 = icmp slt i32 %i3, %sub112 br i1 %cmp1, label %for.body, label %for.cond.cleanup113 114for.cond.cleanup:115 call void @llvm.lifetime.end.p0(ptr %i)116 br label %for.end117 118for.body:119 call void @f0()120 call void @f1()121 br label %for.inc122 123for.inc:124 %i6 = load i32, ptr %i, align 4125 %inc = add nsw i32 %i6, 1126 store i32 %inc, ptr %i, align 4127 br label %for.cond128 129for.end:130 call void @f0()131 call void @f2()132 br label %return133 134return:135 ret void136}137