1044 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=x86_64-pc-linux -x86-cmov-converter=true -verify-machineinstrs -disable-block-placement < %s | FileCheck -allow-deprecated-dag-overlap %s3; RUN: llc -mtriple=x86_64-pc-linux -x86-cmov-converter=true -x86-cmov-converter-force-all=true -verify-machineinstrs -disable-block-placement < %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix=CHECK-FORCEALL4 5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6;; This test checks that x86-cmov-converter optimization transform CMOV7;; instruction into branches when it is profitable.8;; There are 5 cases below:9;; 1. CmovInCriticalPath:10;; CMOV depends on the condition and it is in the hot path.11;; Thus, it worths transforming.12;;13;; 2. CmovNotInCriticalPath:14;; Similar test like in (1), just that CMOV is not in the hot path.15;; Thus, it does not worth transforming.16;;17;; 3. MaxIndex:18;; Maximum calculation algorithm that is looking for the max index,19;; calculating CMOV value is cheaper than calculating CMOV condition.20;; Thus, it worths transforming.21;;22;; 4. MaxValue:23;; Maximum calculation algorithm that is looking for the max value,24;; calculating CMOV value is not cheaper than calculating CMOV condition.25;; Thus, it does not worth transforming.26;;27;; 5. BinarySearch:28;; Usually, binary search CMOV is not predicted.29;; Thus, it does not worth transforming.30;;31;; Test was created using the following command line:32;; > clang -S -O2 -m64 -fno-vectorize -fno-unroll-loops -emit-llvm foo.c -o -33;; Where foo.c is:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35;;void CmovInHotPath(int n, int a, int b, int *c, int *d) {36;; for (int i = 0; i < n; i++) {37;; int t = c[i] + 1;38;; if (cptr a > b)39;; t = 10;40;; c[i] = (c[i] + 1) * t;41;; }42;;}43;;44;;45;;void CmovNotInHotPath(int n, int a, int b, int *c, int *d) {46;; for (int i = 0; i < n; i++) {47;; int t = c[i];48;; if (cptr a > b)49;; t = 10;50;; c[i] = t;51;; d[i] /= b;52;; }53;;}54;;55;;56;;int MaxIndex(int n, int *a) {57;; int t = 0;58;; for (int i = 1; i < n; i++) {59;; if (a[i] > a[t])60;; t = i;61;; }62;; return t;63;;}64;;65;;66;;int MaxValue(int n, int *a) {67;; int t = a[0];68;; for (int i = 1; i < n; i++) {69;; if (a[i] > t)70;; t = a[i];71;; }72;; return t;73;;}74;;75;;typedef struct Node Node;76;;struct Node {77;; unsigned Val;78;; Node *Right;79;; Node *Left;80;;};81;;82;;unsigned BinarySearch(unsigned Mask, Node *Curr, Node *Next) {83;; while (Curr->Val > Next->Val) {84;; Curr = Next;85;; if (Mask & (0x1 << Curr->Val))86;; Next = Curr->Right;87;; else88;; Next = Curr->Left;89;; }90;; return Curr->Val;91;;}92;;93;;94;;void SmallGainPerLoop(int n, int a, int b, int *c, int *d) {95;; for (int i = 0; i < n; i++) {96;; int t = c[i];97;; if (cptr a > b)98;; t = 10;99;; c[i] = t;100;; }101;;}102;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103 104%struct.Node = type { i32, ptr, ptr }105 106define void @CmovInHotPath(i32 %n, i32 %a, i32 %b, ptr nocapture %c, ptr nocapture readnone %d) #0 {107; CHECK-LABEL: CmovInHotPath:108; CHECK: # %bb.0: # %entry109; CHECK-NEXT: testl %edi, %edi110; CHECK-NEXT: jle .LBB0_5111; CHECK-NEXT: # %bb.1: # %for.body.preheader112; CHECK-NEXT: movl %edi, %eax113; CHECK-NEXT: xorl %edi, %edi114; CHECK-NEXT: .LBB0_2: # %for.body115; CHECK-NEXT: # =>This Inner Loop Header: Depth=1116; CHECK-NEXT: movl (%rcx,%rdi,4), %r10d117; CHECK-NEXT: leal 1(%r10), %r8d118; CHECK-NEXT: imull %esi, %r10d119; CHECK-NEXT: movl $10, %r9d120; CHECK-NEXT: cmpl %edx, %r10d121; CHECK-NEXT: jg .LBB0_4122; CHECK-NEXT: # %bb.3: # %for.body123; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1124; CHECK-NEXT: movl %r8d, %r9d125; CHECK-NEXT: .LBB0_4: # %for.body126; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1127; CHECK-NEXT: imull %r8d, %r9d128; CHECK-NEXT: movl %r9d, (%rcx,%rdi,4)129; CHECK-NEXT: addq $1, %rdi130; CHECK-NEXT: cmpq %rdi, %rax131; CHECK-NEXT: jne .LBB0_2132; CHECK-NEXT: .LBB0_5: # %for.cond.cleanup133; CHECK-NEXT: retq134;135; CHECK-FORCEALL-LABEL: CmovInHotPath:136; CHECK-FORCEALL: # %bb.0: # %entry137; CHECK-FORCEALL-NEXT: testl %edi, %edi138; CHECK-FORCEALL-NEXT: jle .LBB0_5139; CHECK-FORCEALL-NEXT: # %bb.1: # %for.body.preheader140; CHECK-FORCEALL-NEXT: movl %edi, %eax141; CHECK-FORCEALL-NEXT: xorl %edi, %edi142; CHECK-FORCEALL-NEXT: .LBB0_2: # %for.body143; CHECK-FORCEALL-NEXT: # =>This Inner Loop Header: Depth=1144; CHECK-FORCEALL-NEXT: movl (%rcx,%rdi,4), %r10d145; CHECK-FORCEALL-NEXT: leal 1(%r10), %r8d146; CHECK-FORCEALL-NEXT: imull %esi, %r10d147; CHECK-FORCEALL-NEXT: movl $10, %r9d148; CHECK-FORCEALL-NEXT: cmpl %edx, %r10d149; CHECK-FORCEALL-NEXT: jg .LBB0_4150; CHECK-FORCEALL-NEXT: # %bb.3: # %for.body151; CHECK-FORCEALL-NEXT: # in Loop: Header=BB0_2 Depth=1152; CHECK-FORCEALL-NEXT: movl %r8d, %r9d153; CHECK-FORCEALL-NEXT: .LBB0_4: # %for.body154; CHECK-FORCEALL-NEXT: # in Loop: Header=BB0_2 Depth=1155; CHECK-FORCEALL-NEXT: imull %r8d, %r9d156; CHECK-FORCEALL-NEXT: movl %r9d, (%rcx,%rdi,4)157; CHECK-FORCEALL-NEXT: addq $1, %rdi158; CHECK-FORCEALL-NEXT: cmpq %rdi, %rax159; CHECK-FORCEALL-NEXT: jne .LBB0_2160; CHECK-FORCEALL-NEXT: .LBB0_5: # %for.cond.cleanup161; CHECK-FORCEALL-NEXT: retq162entry:163 %cmp14 = icmp sgt i32 %n, 0164 br i1 %cmp14, label %for.body.preheader, label %for.cond.cleanup165 166for.body.preheader: ; preds = %entry167 %wide.trip.count = zext i32 %n to i64168 br label %for.body169 170for.cond.cleanup: ; preds = %for.body, %entry171 ret void172 173for.body: ; preds = %for.body.preheader, %for.body174 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ]175 %arrayidx = getelementptr inbounds i32, ptr %c, i64 %indvars.iv176 %0 = load i32, ptr %arrayidx, align 4177 %add = add nsw i32 %0, 1178 %mul = mul nsw i32 %0, %a179 %cmp3 = icmp sgt i32 %mul, %b180 %. = select i1 %cmp3, i32 10, i32 %add181 %mul7 = mul nsw i32 %., %add182 store i32 %mul7, ptr %arrayidx, align 4183 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1184 %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count185 br i1 %exitcond, label %for.cond.cleanup, label %for.body186}187 188define void @CmovNotInHotPath(i32 %n, i32 %a, i32 %b, ptr nocapture %c, ptr nocapture %d) #0 {189; CHECK-LABEL: CmovNotInHotPath:190; CHECK: # %bb.0: # %entry191; CHECK-NEXT: testl %edi, %edi192; CHECK-NEXT: jle .LBB1_3193; CHECK-NEXT: # %bb.1: # %for.body.preheader194; CHECK-NEXT: movl %edx, %r9d195; CHECK-NEXT: movl %edi, %edi196; CHECK-NEXT: xorl %r10d, %r10d197; CHECK-NEXT: movl $10, %r11d198; CHECK-NEXT: .LBB1_2: # %for.body199; CHECK-NEXT: # =>This Inner Loop Header: Depth=1200; CHECK-NEXT: movl (%rcx,%r10,4), %eax201; CHECK-NEXT: movl %eax, %edx202; CHECK-NEXT: imull %esi, %edx203; CHECK-NEXT: cmpl %r9d, %edx204; CHECK-NEXT: cmovgl %r11d, %eax205; CHECK-NEXT: movl %eax, (%rcx,%r10,4)206; CHECK-NEXT: movl (%r8,%r10,4), %eax207; CHECK-NEXT: cltd208; CHECK-NEXT: idivl %r9d209; CHECK-NEXT: movl %eax, (%r8,%r10,4)210; CHECK-NEXT: addq $1, %r10211; CHECK-NEXT: cmpq %r10, %rdi212; CHECK-NEXT: jne .LBB1_2213; CHECK-NEXT: .LBB1_3: # %for.cond.cleanup214; CHECK-NEXT: retq215;216; CHECK-FORCEALL-LABEL: CmovNotInHotPath:217; CHECK-FORCEALL: # %bb.0: # %entry218; CHECK-FORCEALL-NEXT: testl %edi, %edi219; CHECK-FORCEALL-NEXT: jle .LBB1_5220; CHECK-FORCEALL-NEXT: # %bb.1: # %for.body.preheader221; CHECK-FORCEALL-NEXT: movl %edx, %r9d222; CHECK-FORCEALL-NEXT: movl %edi, %edi223; CHECK-FORCEALL-NEXT: xorl %r10d, %r10d224; CHECK-FORCEALL-NEXT: .LBB1_2: # %for.body225; CHECK-FORCEALL-NEXT: # =>This Inner Loop Header: Depth=1226; CHECK-FORCEALL-NEXT: movl (%rcx,%r10,4), %eax227; CHECK-FORCEALL-NEXT: movl %eax, %r11d228; CHECK-FORCEALL-NEXT: imull %esi, %r11d229; CHECK-FORCEALL-NEXT: movl $10, %edx230; CHECK-FORCEALL-NEXT: cmpl %r9d, %r11d231; CHECK-FORCEALL-NEXT: jg .LBB1_4232; CHECK-FORCEALL-NEXT: # %bb.3: # %for.body233; CHECK-FORCEALL-NEXT: # in Loop: Header=BB1_2 Depth=1234; CHECK-FORCEALL-NEXT: movl %eax, %edx235; CHECK-FORCEALL-NEXT: .LBB1_4: # %for.body236; CHECK-FORCEALL-NEXT: # in Loop: Header=BB1_2 Depth=1237; CHECK-FORCEALL-NEXT: movl %edx, (%rcx,%r10,4)238; CHECK-FORCEALL-NEXT: movl (%r8,%r10,4), %eax239; CHECK-FORCEALL-NEXT: cltd240; CHECK-FORCEALL-NEXT: idivl %r9d241; CHECK-FORCEALL-NEXT: movl %eax, (%r8,%r10,4)242; CHECK-FORCEALL-NEXT: addq $1, %r10243; CHECK-FORCEALL-NEXT: cmpq %r10, %rdi244; CHECK-FORCEALL-NEXT: jne .LBB1_2245; CHECK-FORCEALL-NEXT: .LBB1_5: # %for.cond.cleanup246; CHECK-FORCEALL-NEXT: retq247entry:248 %cmp18 = icmp sgt i32 %n, 0249 br i1 %cmp18, label %for.body.preheader, label %for.cond.cleanup250 251for.body.preheader: ; preds = %entry252 %wide.trip.count = zext i32 %n to i64253 br label %for.body254 255for.cond.cleanup: ; preds = %for.body, %entry256 ret void257 258for.body: ; preds = %for.body.preheader, %for.body259 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ]260 %arrayidx = getelementptr inbounds i32, ptr %c, i64 %indvars.iv261 %0 = load i32, ptr %arrayidx, align 4262 %mul = mul nsw i32 %0, %a263 %cmp3 = icmp sgt i32 %mul, %b264 %. = select i1 %cmp3, i32 10, i32 %0265 store i32 %., ptr %arrayidx, align 4266 %arrayidx7 = getelementptr inbounds i32, ptr %d, i64 %indvars.iv267 %1 = load i32, ptr %arrayidx7, align 4268 %div = sdiv i32 %1, %b269 store i32 %div, ptr %arrayidx7, align 4270 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1271 %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count272 br i1 %exitcond, label %for.cond.cleanup, label %for.body273}274 275define i32 @MaxIndex(i32 %n, ptr nocapture readonly %a) #0 {276; CHECK-LABEL: MaxIndex:277; CHECK: # %bb.0: # %entry278; CHECK-NEXT: xorl %eax, %eax279; CHECK-NEXT: cmpl $2, %edi280; CHECK-NEXT: jl .LBB2_5281; CHECK-NEXT: # %bb.1: # %for.body.preheader282; CHECK-NEXT: movl %edi, %ecx283; CHECK-NEXT: xorl %edi, %edi284; CHECK-NEXT: movl $1, %edx285; CHECK-NEXT: .LBB2_2: # %for.body286; CHECK-NEXT: # =>This Inner Loop Header: Depth=1287; CHECK-NEXT: movl (%rsi,%rdx,4), %r8d288; CHECK-NEXT: movslq %edi, %r9289; CHECK-NEXT: movl %edx, %eax290; CHECK-NEXT: cmpl (%rsi,%r9,4), %r8d291; CHECK-NEXT: jg .LBB2_4292; CHECK-NEXT: # %bb.3: # %for.body293; CHECK-NEXT: # in Loop: Header=BB2_2 Depth=1294; CHECK-NEXT: movl %edi, %eax295; CHECK-NEXT: .LBB2_4: # %for.body296; CHECK-NEXT: # in Loop: Header=BB2_2 Depth=1297; CHECK-NEXT: addq $1, %rdx298; CHECK-NEXT: movl %eax, %edi299; CHECK-NEXT: cmpq %rdx, %rcx300; CHECK-NEXT: jne .LBB2_2301; CHECK-NEXT: .LBB2_5: # %for.cond.cleanup302; CHECK-NEXT: retq303;304; CHECK-FORCEALL-LABEL: MaxIndex:305; CHECK-FORCEALL: # %bb.0: # %entry306; CHECK-FORCEALL-NEXT: xorl %eax, %eax307; CHECK-FORCEALL-NEXT: cmpl $2, %edi308; CHECK-FORCEALL-NEXT: jl .LBB2_5309; CHECK-FORCEALL-NEXT: # %bb.1: # %for.body.preheader310; CHECK-FORCEALL-NEXT: movl %edi, %ecx311; CHECK-FORCEALL-NEXT: xorl %edi, %edi312; CHECK-FORCEALL-NEXT: movl $1, %edx313; CHECK-FORCEALL-NEXT: .LBB2_2: # %for.body314; CHECK-FORCEALL-NEXT: # =>This Inner Loop Header: Depth=1315; CHECK-FORCEALL-NEXT: movl (%rsi,%rdx,4), %r8d316; CHECK-FORCEALL-NEXT: movslq %edi, %r9317; CHECK-FORCEALL-NEXT: movl %edx, %eax318; CHECK-FORCEALL-NEXT: cmpl (%rsi,%r9,4), %r8d319; CHECK-FORCEALL-NEXT: jg .LBB2_4320; CHECK-FORCEALL-NEXT: # %bb.3: # %for.body321; CHECK-FORCEALL-NEXT: # in Loop: Header=BB2_2 Depth=1322; CHECK-FORCEALL-NEXT: movl %edi, %eax323; CHECK-FORCEALL-NEXT: .LBB2_4: # %for.body324; CHECK-FORCEALL-NEXT: # in Loop: Header=BB2_2 Depth=1325; CHECK-FORCEALL-NEXT: addq $1, %rdx326; CHECK-FORCEALL-NEXT: movl %eax, %edi327; CHECK-FORCEALL-NEXT: cmpq %rdx, %rcx328; CHECK-FORCEALL-NEXT: jne .LBB2_2329; CHECK-FORCEALL-NEXT: .LBB2_5: # %for.cond.cleanup330; CHECK-FORCEALL-NEXT: retq331entry:332 %cmp14 = icmp sgt i32 %n, 1333 br i1 %cmp14, label %for.body.preheader, label %for.cond.cleanup334 335for.body.preheader: ; preds = %entry336 %wide.trip.count = zext i32 %n to i64337 br label %for.body338 339for.cond.cleanup: ; preds = %for.body, %entry340 %t.0.lcssa = phi i32 [ 0, %entry ], [ %i.0.t.0, %for.body ]341 ret i32 %t.0.lcssa342 343for.body: ; preds = %for.body.preheader, %for.body344 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 1, %for.body.preheader ]345 %t.015 = phi i32 [ %i.0.t.0, %for.body ], [ 0, %for.body.preheader ]346 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv347 %0 = load i32, ptr %arrayidx, align 4348 %idxprom1 = sext i32 %t.015 to i64349 %arrayidx2 = getelementptr inbounds i32, ptr %a, i64 %idxprom1350 %1 = load i32, ptr %arrayidx2, align 4351 %cmp3 = icmp sgt i32 %0, %1352 %2 = trunc i64 %indvars.iv to i32353 %i.0.t.0 = select i1 %cmp3, i32 %2, i32 %t.015354 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1355 %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count356 br i1 %exitcond, label %for.cond.cleanup, label %for.body357}358 359; If cmov instruction is marked as unpredictable, do not convert it to branch.360define i32 @MaxIndex_unpredictable(i32 %n, ptr nocapture readonly %a) #0 {361; CHECK-LABEL: MaxIndex_unpredictable:362; CHECK: # %bb.0: # %entry363; CHECK-NEXT: xorl %eax, %eax364; CHECK-NEXT: cmpl $2, %edi365; CHECK-NEXT: jl .LBB3_3366; CHECK-NEXT: # %bb.1: # %for.body.preheader367; CHECK-NEXT: movl %edi, %ecx368; CHECK-NEXT: xorl %eax, %eax369; CHECK-NEXT: movl $1, %edx370; CHECK-NEXT: .LBB3_2: # %for.body371; CHECK-NEXT: # =>This Inner Loop Header: Depth=1372; CHECK-NEXT: movl (%rsi,%rdx,4), %edi373; CHECK-NEXT: cltq374; CHECK-NEXT: cmpl (%rsi,%rax,4), %edi375; CHECK-NEXT: cmovgl %edx, %eax376; CHECK-NEXT: addq $1, %rdx377; CHECK-NEXT: cmpq %rdx, %rcx378; CHECK-NEXT: jne .LBB3_2379; CHECK-NEXT: .LBB3_3: # %for.cond.cleanup380; CHECK-NEXT: # kill: def $eax killed $eax killed $rax381; CHECK-NEXT: retq382;383; CHECK-FORCEALL-LABEL: MaxIndex_unpredictable:384; CHECK-FORCEALL: # %bb.0: # %entry385; CHECK-FORCEALL-NEXT: xorl %eax, %eax386; CHECK-FORCEALL-NEXT: cmpl $2, %edi387; CHECK-FORCEALL-NEXT: jl .LBB3_3388; CHECK-FORCEALL-NEXT: # %bb.1: # %for.body.preheader389; CHECK-FORCEALL-NEXT: movl %edi, %ecx390; CHECK-FORCEALL-NEXT: xorl %eax, %eax391; CHECK-FORCEALL-NEXT: movl $1, %edx392; CHECK-FORCEALL-NEXT: .LBB3_2: # %for.body393; CHECK-FORCEALL-NEXT: # =>This Inner Loop Header: Depth=1394; CHECK-FORCEALL-NEXT: movl (%rsi,%rdx,4), %edi395; CHECK-FORCEALL-NEXT: cltq396; CHECK-FORCEALL-NEXT: cmpl (%rsi,%rax,4), %edi397; CHECK-FORCEALL-NEXT: cmovgl %edx, %eax398; CHECK-FORCEALL-NEXT: addq $1, %rdx399; CHECK-FORCEALL-NEXT: cmpq %rdx, %rcx400; CHECK-FORCEALL-NEXT: jne .LBB3_2401; CHECK-FORCEALL-NEXT: .LBB3_3: # %for.cond.cleanup402; CHECK-FORCEALL-NEXT: # kill: def $eax killed $eax killed $rax403; CHECK-FORCEALL-NEXT: retq404entry:405 %cmp14 = icmp sgt i32 %n, 1406 br i1 %cmp14, label %for.body.preheader, label %for.cond.cleanup407 408for.body.preheader: ; preds = %entry409 %wide.trip.count = zext i32 %n to i64410 br label %for.body411 412for.cond.cleanup: ; preds = %for.body, %entry413 %t.0.lcssa = phi i32 [ 0, %entry ], [ %i.0.t.0, %for.body ]414 ret i32 %t.0.lcssa415 416for.body: ; preds = %for.body.preheader, %for.body417 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 1, %for.body.preheader ]418 %t.015 = phi i32 [ %i.0.t.0, %for.body ], [ 0, %for.body.preheader ]419 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv420 %0 = load i32, ptr %arrayidx, align 4421 %idxprom1 = sext i32 %t.015 to i64422 %arrayidx2 = getelementptr inbounds i32, ptr %a, i64 %idxprom1423 %1 = load i32, ptr %arrayidx2, align 4424 %cmp3 = icmp sgt i32 %0, %1425 %2 = trunc i64 %indvars.iv to i32426 %i.0.t.0 = select i1 %cmp3, i32 %2, i32 %t.015, !unpredictable !0427 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1428 %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count429 br i1 %exitcond, label %for.cond.cleanup, label %for.body430}431 432define i32 @MaxValue(i32 %n, ptr nocapture readonly %a) #0 {433; CHECK-LABEL: MaxValue:434; CHECK: # %bb.0: # %entry435; CHECK-NEXT: movl (%rsi), %eax436; CHECK-NEXT: cmpl $2, %edi437; CHECK-NEXT: jl .LBB4_3438; CHECK-NEXT: # %bb.1: # %for.body.preheader439; CHECK-NEXT: movl %edi, %ecx440; CHECK-NEXT: movl $1, %edx441; CHECK-NEXT: .LBB4_2: # %for.body442; CHECK-NEXT: # =>This Inner Loop Header: Depth=1443; CHECK-NEXT: movl (%rsi,%rdx,4), %edi444; CHECK-NEXT: cmpl %eax, %edi445; CHECK-NEXT: cmovgl %edi, %eax446; CHECK-NEXT: addq $1, %rdx447; CHECK-NEXT: cmpq %rdx, %rcx448; CHECK-NEXT: jne .LBB4_2449; CHECK-NEXT: .LBB4_3: # %for.cond.cleanup450; CHECK-NEXT: retq451;452; CHECK-FORCEALL-LABEL: MaxValue:453; CHECK-FORCEALL: # %bb.0: # %entry454; CHECK-FORCEALL-NEXT: movl (%rsi), %r8d455; CHECK-FORCEALL-NEXT: cmpl $2, %edi456; CHECK-FORCEALL-NEXT: jge .LBB4_3457; CHECK-FORCEALL-NEXT: # %bb.1:458; CHECK-FORCEALL-NEXT: movl %r8d, %eax459; CHECK-FORCEALL-NEXT: .LBB4_2: # %for.cond.cleanup460; CHECK-FORCEALL-NEXT: retq461; CHECK-FORCEALL-NEXT: .LBB4_3: # %for.body.preheader462; CHECK-FORCEALL-NEXT: movl %edi, %ecx463; CHECK-FORCEALL-NEXT: movl $1, %edx464; CHECK-FORCEALL-NEXT: .LBB4_4: # %for.body465; CHECK-FORCEALL-NEXT: # =>This Inner Loop Header: Depth=1466; CHECK-FORCEALL-NEXT: movl (%rsi,%rdx,4), %eax467; CHECK-FORCEALL-NEXT: cmpl %r8d, %eax468; CHECK-FORCEALL-NEXT: jg .LBB4_6469; CHECK-FORCEALL-NEXT: # %bb.5: # %for.body470; CHECK-FORCEALL-NEXT: # in Loop: Header=BB4_4 Depth=1471; CHECK-FORCEALL-NEXT: movl %r8d, %eax472; CHECK-FORCEALL-NEXT: .LBB4_6: # %for.body473; CHECK-FORCEALL-NEXT: # in Loop: Header=BB4_4 Depth=1474; CHECK-FORCEALL-NEXT: addq $1, %rdx475; CHECK-FORCEALL-NEXT: movl %eax, %r8d476; CHECK-FORCEALL-NEXT: cmpq %rdx, %rcx477; CHECK-FORCEALL-NEXT: je .LBB4_2478; CHECK-FORCEALL-NEXT: jmp .LBB4_4479entry:480 %0 = load i32, ptr %a, align 4481 %cmp13 = icmp sgt i32 %n, 1482 br i1 %cmp13, label %for.body.preheader, label %for.cond.cleanup483 484for.body.preheader: ; preds = %entry485 %wide.trip.count = zext i32 %n to i64486 br label %for.body487 488for.cond.cleanup: ; preds = %for.body, %entry489 %t.0.lcssa = phi i32 [ %0, %entry ], [ %.t.0, %for.body ]490 ret i32 %t.0.lcssa491 492for.body: ; preds = %for.body.preheader, %for.body493 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 1, %for.body.preheader ]494 %t.014 = phi i32 [ %.t.0, %for.body ], [ %0, %for.body.preheader ]495 %arrayidx1 = getelementptr inbounds i32, ptr %a, i64 %indvars.iv496 %1 = load i32, ptr %arrayidx1, align 4497 %cmp2 = icmp sgt i32 %1, %t.014498 %.t.0 = select i1 %cmp2, i32 %1, i32 %t.014499 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1500 %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count501 br i1 %exitcond, label %for.cond.cleanup, label %for.body502}503 504define i32 @BinarySearch(i32 %Mask, ptr nocapture readonly %Curr, ptr nocapture readonly %Next) #0 {505; CHECK-LABEL: BinarySearch:506; CHECK: # %bb.0: # %entry507; CHECK-NEXT: movl (%rsi), %eax508; CHECK-NEXT: jmp .LBB5_2509; CHECK-NEXT: .LBB5_1: # %while.body510; CHECK-NEXT: # in Loop: Header=BB5_2 Depth=1511; CHECK-NEXT: movl %ecx, %eax512; CHECK-NEXT: xorl %ecx, %ecx513; CHECK-NEXT: btl %eax, %edi514; CHECK-NEXT: setae %cl515; CHECK-NEXT: movq 8(%rdx,%rcx,8), %rdx516; CHECK-NEXT: .LBB5_2: # %while.body517; CHECK-NEXT: # =>This Inner Loop Header: Depth=1518; CHECK-NEXT: movl (%rdx), %ecx519; CHECK-NEXT: cmpl %ecx, %eax520; CHECK-NEXT: ja .LBB5_1521; CHECK-NEXT: # %bb.3: # %while.end522; CHECK-NEXT: retq523;524; CHECK-FORCEALL-LABEL: BinarySearch:525; CHECK-FORCEALL: # %bb.0: # %entry526; CHECK-FORCEALL-NEXT: movl (%rsi), %eax527; CHECK-FORCEALL-NEXT: jmp .LBB5_2528; CHECK-FORCEALL-NEXT: .LBB5_1: # %while.body529; CHECK-FORCEALL-NEXT: # in Loop: Header=BB5_2 Depth=1530; CHECK-FORCEALL-NEXT: movl %ecx, %eax531; CHECK-FORCEALL-NEXT: xorl %ecx, %ecx532; CHECK-FORCEALL-NEXT: btl %eax, %edi533; CHECK-FORCEALL-NEXT: setae %cl534; CHECK-FORCEALL-NEXT: movq 8(%rdx,%rcx,8), %rdx535; CHECK-FORCEALL-NEXT: .LBB5_2: # %while.body536; CHECK-FORCEALL-NEXT: # =>This Inner Loop Header: Depth=1537; CHECK-FORCEALL-NEXT: movl (%rdx), %ecx538; CHECK-FORCEALL-NEXT: cmpl %ecx, %eax539; CHECK-FORCEALL-NEXT: ja .LBB5_1540; CHECK-FORCEALL-NEXT: # %bb.3: # %while.end541; CHECK-FORCEALL-NEXT: retq542entry:543 %0 = load i32, ptr %Curr, align 8544 %1 = load i32, ptr %Next, align 8545 %cmp10 = icmp ugt i32 %0, %1546 br i1 %cmp10, label %while.body, label %while.end547 548while.body: ; preds = %entry, %while.body549 %2 = phi i32 [ %4, %while.body ], [ %1, %entry ]550 %Next.addr.011 = phi ptr [ %3, %while.body ], [ %Next, %entry ]551 %shl = shl i32 1, %2552 %and = and i32 %shl, %Mask553 %tobool = icmp eq i32 %and, 0554 %Left = getelementptr inbounds %struct.Node, ptr %Next.addr.011, i64 0, i32 2555 %Right = getelementptr inbounds %struct.Node, ptr %Next.addr.011, i64 0, i32 1556 %Left.sink = select i1 %tobool, ptr %Left, ptr %Right557 %3 = load ptr, ptr %Left.sink, align 8558 %4 = load i32, ptr %3, align 8559 %cmp = icmp ugt i32 %2, %4560 br i1 %cmp, label %while.body, label %while.end561 562while.end: ; preds = %while.body, %entry563 %.lcssa = phi i32 [ %0, %entry ], [ %2, %while.body ]564 ret i32 %.lcssa565}566 567;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;568;; The following test checks that x86-cmov-converter optimization transforms569;; CMOV instructions into branch correctly.570;;571;; MBB:572;; cond = cmp ...573;; v1 = CMOVgt t1, f1, cond574;; v2 = CMOVle s1, f2, cond575;;576;; Where: t1 = 11, f1 = 22, f2 = a577;;578;; After CMOV transformation579;; -------------------------580;; MBB:581;; cond = cmp ...582;; ja %SinkMBB583;;584;; FalseMBB:585;; jmp %SinkMBB586;;587;; SinkMBB:588;; %v1 = phi[%f1, %FalseMBB], [%t1, %MBB]589;; %v2 = phi[%f1, %FalseMBB], [%f2, %MBB] ; For CMOV with OppCC switch590;; ; true-value with false-value591;; ; Phi instruction cannot use592;; ; previous Phi instruction result593;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;594 595define void @Transform(ptr%arr, ptr%arr2, i32 %a, i32 %b, i32 %c, i32 %n) #0 {596; CHECK-LABEL: Transform:597; CHECK: # %bb.0: # %entry598; CHECK-NEXT: movb $1, %al599; CHECK-NEXT: testb %al, %al600; CHECK-NEXT: jne .LBB6_5601; CHECK-NEXT: # %bb.1: # %while.body.preheader602; CHECK-NEXT: movl %edx, %ecx603; CHECK-NEXT: xorl %esi, %esi604; CHECK-NEXT: .LBB6_2: # %while.body605; CHECK-NEXT: # =>This Inner Loop Header: Depth=1606; CHECK-NEXT: movslq %esi, %rsi607; CHECK-NEXT: movl (%rdi,%rsi,4), %eax608; CHECK-NEXT: xorl %edx, %edx609; CHECK-NEXT: divl %ecx610; CHECK-NEXT: movl %eax, %edx611; CHECK-NEXT: movl $11, %eax612; CHECK-NEXT: movl %ecx, %r8d613; CHECK-NEXT: cmpl %ecx, %edx614; CHECK-NEXT: ja .LBB6_4615; CHECK-NEXT: # %bb.3: # %while.body616; CHECK-NEXT: # in Loop: Header=BB6_2 Depth=1617; CHECK-NEXT: movl $22, %eax618; CHECK-NEXT: movl $22, %r8d619; CHECK-NEXT: .LBB6_4: # %while.body620; CHECK-NEXT: # in Loop: Header=BB6_2 Depth=1621; CHECK-NEXT: xorl %edx, %edx622; CHECK-NEXT: divl %r8d623; CHECK-NEXT: movl %edx, (%rdi,%rsi,4)624; CHECK-NEXT: addl $1, %esi625; CHECK-NEXT: cmpl %r9d, %esi626; CHECK-NEXT: ja .LBB6_2627; CHECK-NEXT: .LBB6_5: # %while.end628; CHECK-NEXT: retq629;630; CHECK-FORCEALL-LABEL: Transform:631; CHECK-FORCEALL: # %bb.0: # %entry632; CHECK-FORCEALL-NEXT: movb $1, %al633; CHECK-FORCEALL-NEXT: testb %al, %al634; CHECK-FORCEALL-NEXT: jne .LBB6_5635; CHECK-FORCEALL-NEXT: # %bb.1: # %while.body.preheader636; CHECK-FORCEALL-NEXT: movl %edx, %ecx637; CHECK-FORCEALL-NEXT: xorl %esi, %esi638; CHECK-FORCEALL-NEXT: .LBB6_2: # %while.body639; CHECK-FORCEALL-NEXT: # =>This Inner Loop Header: Depth=1640; CHECK-FORCEALL-NEXT: movslq %esi, %rsi641; CHECK-FORCEALL-NEXT: movl (%rdi,%rsi,4), %eax642; CHECK-FORCEALL-NEXT: xorl %edx, %edx643; CHECK-FORCEALL-NEXT: divl %ecx644; CHECK-FORCEALL-NEXT: movl %eax, %edx645; CHECK-FORCEALL-NEXT: movl $11, %eax646; CHECK-FORCEALL-NEXT: movl %ecx, %r8d647; CHECK-FORCEALL-NEXT: cmpl %ecx, %edx648; CHECK-FORCEALL-NEXT: ja .LBB6_4649; CHECK-FORCEALL-NEXT: # %bb.3: # %while.body650; CHECK-FORCEALL-NEXT: # in Loop: Header=BB6_2 Depth=1651; CHECK-FORCEALL-NEXT: movl $22, %eax652; CHECK-FORCEALL-NEXT: movl $22, %r8d653; CHECK-FORCEALL-NEXT: .LBB6_4: # %while.body654; CHECK-FORCEALL-NEXT: # in Loop: Header=BB6_2 Depth=1655; CHECK-FORCEALL-NEXT: xorl %edx, %edx656; CHECK-FORCEALL-NEXT: divl %r8d657; CHECK-FORCEALL-NEXT: movl %edx, (%rdi,%rsi,4)658; CHECK-FORCEALL-NEXT: addl $1, %esi659; CHECK-FORCEALL-NEXT: cmpl %r9d, %esi660; CHECK-FORCEALL-NEXT: ja .LBB6_2661; CHECK-FORCEALL-NEXT: .LBB6_5: # %while.end662; CHECK-FORCEALL-NEXT: retq663entry:664 %cmp10 = icmp ugt i32 0, %n665 br i1 %cmp10, label %while.body, label %while.end666 667while.body: ; preds = %entry, %while.body668 %i = phi i32 [ %i_inc, %while.body ], [ 0, %entry ]669 %arr_i = getelementptr inbounds i32, ptr %arr, i32 %i670 %x = load i32, ptr %arr_i, align 4671 %div = udiv i32 %x, %a672 %cond = icmp ugt i32 %div, %a673 %condOpp = icmp ule i32 %div, %a674 %s1 = select i1 %cond, i32 11, i32 22675 %s2 = select i1 %condOpp, i32 %s1, i32 %a676 %sum = urem i32 %s1, %s2677 store i32 %sum, ptr %arr_i, align 4678 %i_inc = add i32 %i, 1679 %cmp = icmp ugt i32 %i_inc, %n680 br i1 %cmp, label %while.body, label %while.end681 682while.end: ; preds = %while.body, %entry683 ret void684}685 686; Test that we always will convert a cmov with a memory operand into a branch,687; even outside of a loop.688define i32 @test_cmov_memoperand(i32 %a, i32 %b, i32 %x, ptr %y) #0 {689; CHECK-LABEL: test_cmov_memoperand:690; CHECK: # %bb.0: # %entry691; CHECK-NEXT: movl %edx, %eax692; CHECK-NEXT: cmpl %esi, %edi693; CHECK-NEXT: ja .LBB7_2694; CHECK-NEXT: # %bb.1: # %entry695; CHECK-NEXT: movl (%rcx), %eax696; CHECK-NEXT: .LBB7_2: # %entry697; CHECK-NEXT: retq698;699; CHECK-FORCEALL-LABEL: test_cmov_memoperand:700; CHECK-FORCEALL: # %bb.0: # %entry701; CHECK-FORCEALL-NEXT: movl %edx, %eax702; CHECK-FORCEALL-NEXT: cmpl %esi, %edi703; CHECK-FORCEALL-NEXT: ja .LBB7_2704; CHECK-FORCEALL-NEXT: # %bb.1: # %entry705; CHECK-FORCEALL-NEXT: movl (%rcx), %eax706; CHECK-FORCEALL-NEXT: .LBB7_2: # %entry707; CHECK-FORCEALL-NEXT: retq708entry:709 %cond = icmp ugt i32 %a, %b710 %load = load i32, ptr %y711 %z = select i1 %cond, i32 %x, i32 %load712 ret i32 %z713}714 715; If cmov instruction is marked as unpredictable, do not convert it to branch.716define i32 @test_cmov_memoperand_unpredictable(i32 %a, i32 %b, i32 %x, ptr %y) #0 {717; CHECK-LABEL: test_cmov_memoperand_unpredictable:718; CHECK: # %bb.0: # %entry719; CHECK-NEXT: movl %edx, %eax720; CHECK-NEXT: cmpl %esi, %edi721; CHECK-NEXT: cmovbel (%rcx), %eax722; CHECK-NEXT: retq723;724; CHECK-FORCEALL-LABEL: test_cmov_memoperand_unpredictable:725; CHECK-FORCEALL: # %bb.0: # %entry726; CHECK-FORCEALL-NEXT: movl %edx, %eax727; CHECK-FORCEALL-NEXT: cmpl %esi, %edi728; CHECK-FORCEALL-NEXT: cmovbel (%rcx), %eax729; CHECK-FORCEALL-NEXT: retq730entry:731 %cond = icmp ugt i32 %a, %b732 %load = load i32, ptr %y733 %z = select i1 %cond, i32 %x, i32 %load, !unpredictable !0734 ret i32 %z735}736 737; Test that we can convert a group of cmovs where only one has a memory738; operand.739define i32 @test_cmov_memoperand_in_group(i32 %a, i32 %b, i32 %x, ptr %y.ptr) #0 {740; CHECK-LABEL: test_cmov_memoperand_in_group:741; CHECK: # %bb.0: # %entry742; CHECK-NEXT: movl %edx, %eax743; CHECK-NEXT: movl %edx, %r8d744; CHECK-NEXT: cmpl %esi, %edi745; CHECK-NEXT: ja .LBB9_2746; CHECK-NEXT: # %bb.1: # %entry747; CHECK-NEXT: movl (%rcx), %edx748; CHECK-NEXT: movl %edi, %eax749; CHECK-NEXT: movl %esi, %r8d750; CHECK-NEXT: .LBB9_2: # %entry751; CHECK-NEXT: addl %r8d, %eax752; CHECK-NEXT: addl %edx, %eax753; CHECK-NEXT: retq754;755; CHECK-FORCEALL-LABEL: test_cmov_memoperand_in_group:756; CHECK-FORCEALL: # %bb.0: # %entry757; CHECK-FORCEALL-NEXT: movl %edx, %eax758; CHECK-FORCEALL-NEXT: movl %edx, %r8d759; CHECK-FORCEALL-NEXT: cmpl %esi, %edi760; CHECK-FORCEALL-NEXT: ja .LBB9_2761; CHECK-FORCEALL-NEXT: # %bb.1: # %entry762; CHECK-FORCEALL-NEXT: movl (%rcx), %edx763; CHECK-FORCEALL-NEXT: movl %edi, %eax764; CHECK-FORCEALL-NEXT: movl %esi, %r8d765; CHECK-FORCEALL-NEXT: .LBB9_2: # %entry766; CHECK-FORCEALL-NEXT: addl %r8d, %eax767; CHECK-FORCEALL-NEXT: addl %edx, %eax768; CHECK-FORCEALL-NEXT: retq769entry:770 %cond = icmp ugt i32 %a, %b771 %y = load i32, ptr %y.ptr772 %z1 = select i1 %cond, i32 %x, i32 %a773 %z2 = select i1 %cond, i32 %x, i32 %y774 %z3 = select i1 %cond, i32 %x, i32 %b775 %s1 = add i32 %z1, %z2776 %s2 = add i32 %s1, %z3777 ret i32 %s2778}779 780; Same as before but with operands reversed in the select with a load.781define i32 @test_cmov_memoperand_in_group2(i32 %a, i32 %b, i32 %x, ptr %y.ptr) #0 {782; CHECK-LABEL: test_cmov_memoperand_in_group2:783; CHECK: # %bb.0: # %entry784; CHECK-NEXT: movl %edx, %eax785; CHECK-NEXT: movl %edx, %r8d786; CHECK-NEXT: cmpl %esi, %edi787; CHECK-NEXT: jbe .LBB10_2788; CHECK-NEXT: # %bb.1: # %entry789; CHECK-NEXT: movl (%rcx), %edx790; CHECK-NEXT: movl %edi, %eax791; CHECK-NEXT: movl %esi, %r8d792; CHECK-NEXT: .LBB10_2: # %entry793; CHECK-NEXT: addl %r8d, %eax794; CHECK-NEXT: addl %edx, %eax795; CHECK-NEXT: retq796;797; CHECK-FORCEALL-LABEL: test_cmov_memoperand_in_group2:798; CHECK-FORCEALL: # %bb.0: # %entry799; CHECK-FORCEALL-NEXT: movl %edx, %eax800; CHECK-FORCEALL-NEXT: movl %edx, %r8d801; CHECK-FORCEALL-NEXT: cmpl %esi, %edi802; CHECK-FORCEALL-NEXT: jbe .LBB10_2803; CHECK-FORCEALL-NEXT: # %bb.1: # %entry804; CHECK-FORCEALL-NEXT: movl (%rcx), %edx805; CHECK-FORCEALL-NEXT: movl %edi, %eax806; CHECK-FORCEALL-NEXT: movl %esi, %r8d807; CHECK-FORCEALL-NEXT: .LBB10_2: # %entry808; CHECK-FORCEALL-NEXT: addl %r8d, %eax809; CHECK-FORCEALL-NEXT: addl %edx, %eax810; CHECK-FORCEALL-NEXT: retq811entry:812 %cond = icmp ugt i32 %a, %b813 %y = load i32, ptr %y.ptr814 %z2 = select i1 %cond, i32 %a, i32 %x815 %z1 = select i1 %cond, i32 %y, i32 %x816 %z3 = select i1 %cond, i32 %b, i32 %x817 %s1 = add i32 %z1, %z2818 %s2 = add i32 %s1, %z3819 ret i32 %s2820}821 822; Test that we don't convert a group of cmovs with conflicting directions of823; loads.824define i32 @test_cmov_memoperand_conflicting_dir(i32 %a, i32 %b, i32 %x, ptr %y1.ptr, ptr %y2.ptr) #0 {825; CHECK-LABEL: test_cmov_memoperand_conflicting_dir:826; CHECK: # %bb.0: # %entry827; CHECK-NEXT: cmpl %esi, %edi828; CHECK-NEXT: movl (%rcx), %eax829; CHECK-NEXT: cmoval %edx, %eax830; CHECK-NEXT: cmoval (%r8), %edx831; CHECK-NEXT: addl %edx, %eax832; CHECK-NEXT: retq833;834; CHECK-FORCEALL-LABEL: test_cmov_memoperand_conflicting_dir:835; CHECK-FORCEALL: # %bb.0: # %entry836; CHECK-FORCEALL-NEXT: cmpl %esi, %edi837; CHECK-FORCEALL-NEXT: movl (%rcx), %eax838; CHECK-FORCEALL-NEXT: cmoval %edx, %eax839; CHECK-FORCEALL-NEXT: cmoval (%r8), %edx840; CHECK-FORCEALL-NEXT: addl %edx, %eax841; CHECK-FORCEALL-NEXT: retq842entry:843 %cond = icmp ugt i32 %a, %b844 %y1 = load i32, ptr %y1.ptr845 %y2 = load i32, ptr %y2.ptr846 %z1 = select i1 %cond, i32 %x, i32 %y1847 %z2 = select i1 %cond, i32 %y2, i32 %x848 %s1 = add i32 %z1, %z2849 ret i32 %s1850}851 852; Test that we can convert a group of cmovs where only one has a memory853; operand and where that memory operand's registers come from a prior cmov in854; the group.855define i32 @test_cmov_memoperand_in_group_reuse_for_addr(i32 %a, i32 %b, ptr %x, ptr %y) #0 {856; CHECK-LABEL: test_cmov_memoperand_in_group_reuse_for_addr:857; CHECK: # %bb.0: # %entry858; CHECK-NEXT: movl %edi, %eax859; CHECK-NEXT: cmpl %esi, %edi860; CHECK-NEXT: ja .LBB12_2861; CHECK-NEXT: # %bb.1: # %entry862; CHECK-NEXT: movl (%rcx), %eax863; CHECK-NEXT: .LBB12_2: # %entry864; CHECK-NEXT: retq865;866; CHECK-FORCEALL-LABEL: test_cmov_memoperand_in_group_reuse_for_addr:867; CHECK-FORCEALL: # %bb.0: # %entry868; CHECK-FORCEALL-NEXT: movl %edi, %eax869; CHECK-FORCEALL-NEXT: cmpl %esi, %edi870; CHECK-FORCEALL-NEXT: ja .LBB12_2871; CHECK-FORCEALL-NEXT: # %bb.1: # %entry872; CHECK-FORCEALL-NEXT: movl (%rcx), %eax873; CHECK-FORCEALL-NEXT: .LBB12_2: # %entry874; CHECK-FORCEALL-NEXT: retq875entry:876 %cond = icmp ugt i32 %a, %b877 %p = select i1 %cond, ptr %x, ptr %y878 %load = load i32, ptr %p879 %z = select i1 %cond, i32 %a, i32 %load880 ret i32 %z881}882 883; Test that we can convert a group of two cmovs with memory operands where one884; uses the result of the other as part of the address.885define i32 @test_cmov_memoperand_in_group_reuse_for_addr2(i32 %a, i32 %b, ptr %x, ptr %y) #0 {886; CHECK-LABEL: test_cmov_memoperand_in_group_reuse_for_addr2:887; CHECK: # %bb.0: # %entry888; CHECK-NEXT: movl %edi, %eax889; CHECK-NEXT: cmpl %esi, %edi890; CHECK-NEXT: ja .LBB13_2891; CHECK-NEXT: # %bb.1: # %entry892; CHECK-NEXT: movq (%rcx), %rax893; CHECK-NEXT: movl (%rax), %eax894; CHECK-NEXT: .LBB13_2: # %entry895; CHECK-NEXT: retq896;897; CHECK-FORCEALL-LABEL: test_cmov_memoperand_in_group_reuse_for_addr2:898; CHECK-FORCEALL: # %bb.0: # %entry899; CHECK-FORCEALL-NEXT: movl %edi, %eax900; CHECK-FORCEALL-NEXT: cmpl %esi, %edi901; CHECK-FORCEALL-NEXT: ja .LBB13_2902; CHECK-FORCEALL-NEXT: # %bb.1: # %entry903; CHECK-FORCEALL-NEXT: movq (%rcx), %rax904; CHECK-FORCEALL-NEXT: movl (%rax), %eax905; CHECK-FORCEALL-NEXT: .LBB13_2: # %entry906; CHECK-FORCEALL-NEXT: retq907entry:908 %cond = icmp ugt i32 %a, %b909 %load1 = load ptr, ptr %y910 %p = select i1 %cond, ptr %x, ptr %load1911 %load2 = load i32, ptr %p912 %z = select i1 %cond, i32 %a, i32 %load2913 ret i32 %z914}915 916; Test that we can convert a group of cmovs where only one has a memory917; operand and where that memory operand's registers come from a prior cmov and918; where that cmov gets *its* input from a prior cmov in the group.919define i32 @test_cmov_memoperand_in_group_reuse_for_addr3(i32 %a, i32 %b, ptr %x, ptr %y, ptr %z) #0 {920; CHECK-LABEL: test_cmov_memoperand_in_group_reuse_for_addr3:921; CHECK: # %bb.0: # %entry922; CHECK-NEXT: movl %edi, %eax923; CHECK-NEXT: cmpl %esi, %edi924; CHECK-NEXT: ja .LBB14_2925; CHECK-NEXT: # %bb.1: # %entry926; CHECK-NEXT: movl (%rcx), %eax927; CHECK-NEXT: .LBB14_2: # %entry928; CHECK-NEXT: retq929;930; CHECK-FORCEALL-LABEL: test_cmov_memoperand_in_group_reuse_for_addr3:931; CHECK-FORCEALL: # %bb.0: # %entry932; CHECK-FORCEALL-NEXT: movl %edi, %eax933; CHECK-FORCEALL-NEXT: cmpl %esi, %edi934; CHECK-FORCEALL-NEXT: ja .LBB14_2935; CHECK-FORCEALL-NEXT: # %bb.1: # %entry936; CHECK-FORCEALL-NEXT: movl (%rcx), %eax937; CHECK-FORCEALL-NEXT: .LBB14_2: # %entry938; CHECK-FORCEALL-NEXT: retq939entry:940 %cond = icmp ugt i32 %a, %b941 %p = select i1 %cond, ptr %x, ptr %y942 %p2 = select i1 %cond, ptr %z, ptr %p943 %load = load i32, ptr %p2944 %r = select i1 %cond, i32 %a, i32 %load945 ret i32 %r946}947 948@begin = external global ptr949@end = external global ptr950 951define void @test_memoperand_loop(i32 %data) #0 {952; CHECK-LABEL: test_memoperand_loop:953; CHECK: # %bb.0: # %entry954; CHECK-NEXT: movq begin@GOTPCREL(%rip), %rax955; CHECK-NEXT: movq (%rax), %rcx956; CHECK-NEXT: movq end@GOTPCREL(%rip), %rdx957; CHECK-NEXT: movq (%rdx), %rdx958; CHECK-NEXT: xorl %esi, %esi959; CHECK-NEXT: movq %rcx, %r8960; CHECK-NEXT: .LBB15_1: # %loop.body961; CHECK-NEXT: # =>This Inner Loop Header: Depth=1962; CHECK-NEXT: addq $8, %r8963; CHECK-NEXT: cmpq %rdx, %r8964; CHECK-NEXT: ja .LBB15_3965; CHECK-NEXT: # %bb.2: # %loop.body966; CHECK-NEXT: # in Loop: Header=BB15_1 Depth=1967; CHECK-NEXT: movq (%rax), %r8968; CHECK-NEXT: .LBB15_3: # %loop.body969; CHECK-NEXT: # in Loop: Header=BB15_1 Depth=1970; CHECK-NEXT: movl %edi, (%r8)971; CHECK-NEXT: addq $8, %r8972; CHECK-NEXT: cmpq %rdx, %r8973; CHECK-NEXT: ja .LBB15_5974; CHECK-NEXT: # %bb.4: # %loop.body975; CHECK-NEXT: # in Loop: Header=BB15_1 Depth=1976; CHECK-NEXT: movq %rcx, %r8977; CHECK-NEXT: .LBB15_5: # %loop.body978; CHECK-NEXT: # in Loop: Header=BB15_1 Depth=1979; CHECK-NEXT: movl %edi, (%r8)980; CHECK-NEXT: addl $1, %esi981; CHECK-NEXT: cmpl $1024, %esi # imm = 0x400982; CHECK-NEXT: jl .LBB15_1983; CHECK-NEXT: # %bb.6: # %exit984; CHECK-NEXT: retq985;986; CHECK-FORCEALL-LABEL: test_memoperand_loop:987; CHECK-FORCEALL: # %bb.0: # %entry988; CHECK-FORCEALL-NEXT: movq begin@GOTPCREL(%rip), %rax989; CHECK-FORCEALL-NEXT: movq (%rax), %rcx990; CHECK-FORCEALL-NEXT: movq end@GOTPCREL(%rip), %rdx991; CHECK-FORCEALL-NEXT: movq (%rdx), %rdx992; CHECK-FORCEALL-NEXT: xorl %esi, %esi993; CHECK-FORCEALL-NEXT: movq %rcx, %r8994; CHECK-FORCEALL-NEXT: .LBB15_1: # %loop.body995; CHECK-FORCEALL-NEXT: # =>This Inner Loop Header: Depth=1996; CHECK-FORCEALL-NEXT: addq $8, %r8997; CHECK-FORCEALL-NEXT: cmpq %rdx, %r8998; CHECK-FORCEALL-NEXT: ja .LBB15_3999; CHECK-FORCEALL-NEXT: # %bb.2: # %loop.body1000; CHECK-FORCEALL-NEXT: # in Loop: Header=BB15_1 Depth=11001; CHECK-FORCEALL-NEXT: movq (%rax), %r81002; CHECK-FORCEALL-NEXT: .LBB15_3: # %loop.body1003; CHECK-FORCEALL-NEXT: # in Loop: Header=BB15_1 Depth=11004; CHECK-FORCEALL-NEXT: movl %edi, (%r8)1005; CHECK-FORCEALL-NEXT: addq $8, %r81006; CHECK-FORCEALL-NEXT: cmpq %rdx, %r81007; CHECK-FORCEALL-NEXT: ja .LBB15_51008; CHECK-FORCEALL-NEXT: # %bb.4: # %loop.body1009; CHECK-FORCEALL-NEXT: # in Loop: Header=BB15_1 Depth=11010; CHECK-FORCEALL-NEXT: movq %rcx, %r81011; CHECK-FORCEALL-NEXT: .LBB15_5: # %loop.body1012; CHECK-FORCEALL-NEXT: # in Loop: Header=BB15_1 Depth=11013; CHECK-FORCEALL-NEXT: movl %edi, (%r8)1014; CHECK-FORCEALL-NEXT: addl $1, %esi1015; CHECK-FORCEALL-NEXT: cmpl $1024, %esi # imm = 0x4001016; CHECK-FORCEALL-NEXT: jl .LBB15_11017; CHECK-FORCEALL-NEXT: # %bb.6: # %exit1018; CHECK-FORCEALL-NEXT: retq1019entry:1020 %begin = load ptr, ptr @begin, align 81021 %end = load ptr, ptr @end, align 81022 br label %loop.body1023loop.body:1024 %phi.iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.body ]1025 %phi.ptr = phi ptr [ %begin, %entry ], [ %dst2, %loop.body ]1026 %gep1 = getelementptr inbounds i32, ptr%phi.ptr, i64 21027 %cmp1 = icmp ugt ptr %gep1, %end1028 %begin_dup = load ptr, ptr @begin, align 81029 %dst1 = select i1 %cmp1, ptr %gep1, ptr %begin_dup1030 store i32 %data, ptr%dst1, align 41031 %gep2 = getelementptr inbounds i32, ptr%dst1, i64 21032 %cmp2 = icmp ugt ptr %gep2, %end1033 %dst2 = select i1 %cmp2, ptr %gep2, ptr %begin1034 store i32 %data, ptr%dst2, align 41035 %iv.next = add i32 %phi.iv, 11036 %cond = icmp slt i32 %iv.next, 10241037 br i1 %cond, label %loop.body, label %exit1038exit:1039 ret void1040}1041 1042attributes #0 = {"target-cpu"="x86-64" "tune-cpu"="x86-64"}1043!0 = !{}1044