16e9e5389SCraig Topper; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2*48c6b272SRoman Lebedev; RUN: opt -passes=loop-idiom -mtriple=x86_64 -mcpu=core-avx2 < %s -S | FileCheck --check-prefix=ALL %s 3*48c6b272SRoman Lebedev; RUN: opt -passes=loop-idiom -mtriple=x86_64 -mcpu=corei7 < %s -S | FileCheck --check-prefix=ALL %s 4cee313d2SEric Christopher 5cee313d2SEric Christopher; Recognize CTTZ builtin pattern. 6cee313d2SEric Christopher; Here it will replace the loop - 7cee313d2SEric Christopher; assume builtin is always profitable. 8cee313d2SEric Christopher; 9cee313d2SEric Christopher; int cttz_zero_check(int n) 10cee313d2SEric Christopher; { 11cee313d2SEric Christopher; int i = 0; 12cee313d2SEric Christopher; while(n) { 13cee313d2SEric Christopher; n <<= 1; 14cee313d2SEric Christopher; i++; 15cee313d2SEric Christopher; } 16cee313d2SEric Christopher; return i; 17cee313d2SEric Christopher; } 18cee313d2SEric Christopher; 19cee313d2SEric Christopherdefine i32 @cttz_zero_check(i32 %n) { 206e9e5389SCraig Topper; ALL-LABEL: @cttz_zero_check( 216e9e5389SCraig Topper; ALL-NEXT: entry: 226e9e5389SCraig Topper; ALL-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[N:%.*]], 0 236e9e5389SCraig Topper; ALL-NEXT: br i1 [[TOBOOL4]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]] 246e9e5389SCraig Topper; ALL: while.body.preheader: 256e9e5389SCraig Topper; ALL-NEXT: [[TMP0:%.*]] = call i32 @llvm.cttz.i32(i32 [[N]], i1 true) 266e9e5389SCraig Topper; ALL-NEXT: [[TMP1:%.*]] = sub i32 32, [[TMP0]] 276e9e5389SCraig Topper; ALL-NEXT: br label [[WHILE_BODY:%.*]] 286e9e5389SCraig Topper; ALL: while.body: 296e9e5389SCraig Topper; ALL-NEXT: [[TCPHI:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY_PREHEADER]] ], [ [[TCDEC:%.*]], [[WHILE_BODY]] ] 306e9e5389SCraig Topper; ALL-NEXT: [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ] 316e9e5389SCraig Topper; ALL-NEXT: [[N_ADDR_05:%.*]] = phi i32 [ [[SHL:%.*]], [[WHILE_BODY]] ], [ [[N]], [[WHILE_BODY_PREHEADER]] ] 326e9e5389SCraig Topper; ALL-NEXT: [[SHL]] = shl i32 [[N_ADDR_05]], 1 336e9e5389SCraig Topper; ALL-NEXT: [[INC]] = add nsw i32 [[I_06]], 1 346e9e5389SCraig Topper; ALL-NEXT: [[TCDEC]] = sub nsw i32 [[TCPHI]], 1 356e9e5389SCraig Topper; ALL-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TCDEC]], 0 366e9e5389SCraig Topper; ALL-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]] 376e9e5389SCraig Topper; ALL: while.end.loopexit: 386e9e5389SCraig Topper; ALL-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY]] ] 396e9e5389SCraig Topper; ALL-NEXT: br label [[WHILE_END]] 406e9e5389SCraig Topper; ALL: while.end: 416e9e5389SCraig Topper; ALL-NEXT: [[I_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ] 426e9e5389SCraig Topper; ALL-NEXT: ret i32 [[I_0_LCSSA]] 436e9e5389SCraig Topper; 44cee313d2SEric Christopherentry: 45cee313d2SEric Christopher %tobool4 = icmp eq i32 %n, 0 46cee313d2SEric Christopher br i1 %tobool4, label %while.end, label %while.body.preheader 47cee313d2SEric Christopher 48cee313d2SEric Christopherwhile.body.preheader: ; preds = %entry 49cee313d2SEric Christopher br label %while.body 50cee313d2SEric Christopher 51cee313d2SEric Christopherwhile.body: ; preds = %while.body.preheader, %while.body 52cee313d2SEric Christopher %i.06 = phi i32 [ %inc, %while.body ], [ 0, %while.body.preheader ] 53cee313d2SEric Christopher %n.addr.05 = phi i32 [ %shl, %while.body ], [ %n, %while.body.preheader ] 54cee313d2SEric Christopher %shl = shl i32 %n.addr.05, 1 55cee313d2SEric Christopher %inc = add nsw i32 %i.06, 1 56cee313d2SEric Christopher %tobool = icmp eq i32 %shl, 0 57cee313d2SEric Christopher br i1 %tobool, label %while.end.loopexit, label %while.body 58cee313d2SEric Christopher 59cee313d2SEric Christopherwhile.end.loopexit: ; preds = %while.body 60cee313d2SEric Christopher br label %while.end 61cee313d2SEric Christopher 62cee313d2SEric Christopherwhile.end: ; preds = %while.end.loopexit, %entry 63cee313d2SEric Christopher %i.0.lcssa = phi i32 [ 0, %entry ], [ %inc, %while.end.loopexit ] 64cee313d2SEric Christopher ret i32 %i.0.lcssa 65cee313d2SEric Christopher} 66cee313d2SEric Christopher 67cee313d2SEric Christopher; Recognize CTTZ builtin pattern. 68cee313d2SEric Christopher; Here it will replace the loop - 69cee313d2SEric Christopher; assume builtin is always profitable. 70cee313d2SEric Christopher; 71cee313d2SEric Christopher; int cttz(int n) 72cee313d2SEric Christopher; { 73cee313d2SEric Christopher; int i = 0; 74cee313d2SEric Christopher; while(n <<= 1) { 75cee313d2SEric Christopher; i++; 76cee313d2SEric Christopher; } 77cee313d2SEric Christopher; return i; 78cee313d2SEric Christopher; } 79cee313d2SEric Christopher; 80cee313d2SEric Christopherdefine i32 @cttz(i32 %n) { 816e9e5389SCraig Topper; ALL-LABEL: @cttz( 826e9e5389SCraig Topper; ALL-NEXT: entry: 836e9e5389SCraig Topper; ALL-NEXT: [[TMP0:%.*]] = shl i32 [[N:%.*]], 1 846e9e5389SCraig Topper; ALL-NEXT: [[TMP1:%.*]] = call i32 @llvm.cttz.i32(i32 [[TMP0]], i1 false) 856e9e5389SCraig Topper; ALL-NEXT: [[TMP2:%.*]] = sub i32 32, [[TMP1]] 866e9e5389SCraig Topper; ALL-NEXT: [[TMP3:%.*]] = add i32 [[TMP2]], 1 876e9e5389SCraig Topper; ALL-NEXT: br label [[WHILE_COND:%.*]] 886e9e5389SCraig Topper; ALL: while.cond: 896e9e5389SCraig Topper; ALL-NEXT: [[TCPHI:%.*]] = phi i32 [ [[TMP3]], [[ENTRY:%.*]] ], [ [[TCDEC:%.*]], [[WHILE_COND]] ] 906e9e5389SCraig Topper; ALL-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[SHL:%.*]], [[WHILE_COND]] ] 916e9e5389SCraig Topper; ALL-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[WHILE_COND]] ] 926e9e5389SCraig Topper; ALL-NEXT: [[SHL]] = shl i32 [[N_ADDR_0]], 1 936e9e5389SCraig Topper; ALL-NEXT: [[TCDEC]] = sub nsw i32 [[TCPHI]], 1 946e9e5389SCraig Topper; ALL-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TCDEC]], 0 956e9e5389SCraig Topper; ALL-NEXT: [[INC]] = add nsw i32 [[I_0]], 1 966e9e5389SCraig Topper; ALL-NEXT: br i1 [[TOBOOL]], label [[WHILE_END:%.*]], label [[WHILE_COND]] 976e9e5389SCraig Topper; ALL: while.end: 986e9e5389SCraig Topper; ALL-NEXT: [[I_0_LCSSA:%.*]] = phi i32 [ [[TMP2]], [[WHILE_COND]] ] 996e9e5389SCraig Topper; ALL-NEXT: ret i32 [[I_0_LCSSA]] 1006e9e5389SCraig Topper; 101cee313d2SEric Christopherentry: 102cee313d2SEric Christopher br label %while.cond 103cee313d2SEric Christopher 104cee313d2SEric Christopherwhile.cond: ; preds = %while.cond, %entry 105cee313d2SEric Christopher %n.addr.0 = phi i32 [ %n, %entry ], [ %shl, %while.cond ] 106cee313d2SEric Christopher %i.0 = phi i32 [ 0, %entry ], [ %inc, %while.cond ] 107cee313d2SEric Christopher %shl = shl i32 %n.addr.0, 1 108cee313d2SEric Christopher %tobool = icmp eq i32 %shl, 0 109cee313d2SEric Christopher %inc = add nsw i32 %i.0, 1 110cee313d2SEric Christopher br i1 %tobool, label %while.end, label %while.cond 111cee313d2SEric Christopher 112cee313d2SEric Christopherwhile.end: ; preds = %while.cond 113cee313d2SEric Christopher ret i32 %i.0 114cee313d2SEric Christopher} 115cee313d2SEric Christopher 1162acd5a47SCraig Topper; Recognize CTTZ builtin pattern. 1172acd5a47SCraig Topper; Here it will replace the loop - 1182acd5a47SCraig Topper; assume builtin is always profitable. 1192acd5a47SCraig Topper; 1202acd5a47SCraig Topper; int ctlz_decrement(int n) 1212acd5a47SCraig Topper; { 1222acd5a47SCraig Topper; int i = 32; 1232acd5a47SCraig Topper; while(n) { 1242acd5a47SCraig Topper; n <<= 1; 1252acd5a47SCraig Topper; i--; 1262acd5a47SCraig Topper; } 1272acd5a47SCraig Topper; return i; 1282acd5a47SCraig Topper; } 1292acd5a47SCraig Topper; 1302acd5a47SCraig Topperdefine i32 @cttz_decrement(i32 %n) { 1312acd5a47SCraig Topper; ALL-LABEL: @cttz_decrement( 1322acd5a47SCraig Topper; ALL-NEXT: entry: 1332acd5a47SCraig Topper; ALL-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[N:%.*]], 0 1342acd5a47SCraig Topper; ALL-NEXT: br i1 [[TOBOOL4]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]] 1352acd5a47SCraig Topper; ALL: while.body.preheader: 13625067f17SCraig Topper; ALL-NEXT: [[TMP0:%.*]] = call i32 @llvm.cttz.i32(i32 [[N]], i1 true) 13725067f17SCraig Topper; ALL-NEXT: [[TMP1:%.*]] = sub i32 32, [[TMP0]] 13825067f17SCraig Topper; ALL-NEXT: [[TMP2:%.*]] = sub i32 32, [[TMP1]] 1392acd5a47SCraig Topper; ALL-NEXT: br label [[WHILE_BODY:%.*]] 1402acd5a47SCraig Topper; ALL: while.body: 14125067f17SCraig Topper; ALL-NEXT: [[TCPHI:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY_PREHEADER]] ], [ [[TCDEC:%.*]], [[WHILE_BODY]] ] 1422acd5a47SCraig Topper; ALL-NEXT: [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 32, [[WHILE_BODY_PREHEADER]] ] 1432acd5a47SCraig Topper; ALL-NEXT: [[N_ADDR_05:%.*]] = phi i32 [ [[SHL:%.*]], [[WHILE_BODY]] ], [ [[N]], [[WHILE_BODY_PREHEADER]] ] 1442acd5a47SCraig Topper; ALL-NEXT: [[SHL]] = shl i32 [[N_ADDR_05]], 1 1452acd5a47SCraig Topper; ALL-NEXT: [[INC]] = add nsw i32 [[I_06]], -1 14625067f17SCraig Topper; ALL-NEXT: [[TCDEC]] = sub nsw i32 [[TCPHI]], 1 14725067f17SCraig Topper; ALL-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TCDEC]], 0 1482acd5a47SCraig Topper; ALL-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]] 1492acd5a47SCraig Topper; ALL: while.end.loopexit: 15025067f17SCraig Topper; ALL-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[TMP2]], [[WHILE_BODY]] ] 1512acd5a47SCraig Topper; ALL-NEXT: br label [[WHILE_END]] 1522acd5a47SCraig Topper; ALL: while.end: 1532acd5a47SCraig Topper; ALL-NEXT: [[I_0_LCSSA:%.*]] = phi i32 [ 32, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ] 1542acd5a47SCraig Topper; ALL-NEXT: ret i32 [[I_0_LCSSA]] 1552acd5a47SCraig Topper; 1562acd5a47SCraig Topperentry: 1572acd5a47SCraig Topper %tobool4 = icmp eq i32 %n, 0 1582acd5a47SCraig Topper br i1 %tobool4, label %while.end, label %while.body.preheader 1592acd5a47SCraig Topper 1602acd5a47SCraig Topperwhile.body.preheader: ; preds = %entry 1612acd5a47SCraig Topper br label %while.body 1622acd5a47SCraig Topper 1632acd5a47SCraig Topperwhile.body: ; preds = %while.body.preheader, %while.body 1642acd5a47SCraig Topper %i.06 = phi i32 [ %inc, %while.body ], [ 32, %while.body.preheader ] 1652acd5a47SCraig Topper %n.addr.05 = phi i32 [ %shl, %while.body ], [ %n, %while.body.preheader ] 1662acd5a47SCraig Topper %shl = shl i32 %n.addr.05, 1 1672acd5a47SCraig Topper %inc = add nsw i32 %i.06, -1 1682acd5a47SCraig Topper %tobool = icmp eq i32 %shl, 0 1692acd5a47SCraig Topper br i1 %tobool, label %while.end.loopexit, label %while.body 1702acd5a47SCraig Topper 1712acd5a47SCraig Topperwhile.end.loopexit: ; preds = %while.body 1722acd5a47SCraig Topper br label %while.end 1732acd5a47SCraig Topper 1742acd5a47SCraig Topperwhile.end: ; preds = %while.end.loopexit, %entry 1752acd5a47SCraig Topper %i.0.lcssa = phi i32 [ 32, %entry ], [ %inc, %while.end.loopexit ] 1762acd5a47SCraig Topper ret i32 %i.0.lcssa 1772acd5a47SCraig Topper} 1782acd5a47SCraig Topper 1792acd5a47SCraig Topper; Recognize CTTZ builtin pattern. 1802acd5a47SCraig Topper; Here it will replace the loop - 1812acd5a47SCraig Topper; assume builtin is always profitable. 1822acd5a47SCraig Topper; 1832acd5a47SCraig Topper; int cttz_shl_decrement(int n) 1842acd5a47SCraig Topper; { 1852acd5a47SCraig Topper; int i = 31; 1862acd5a47SCraig Topper; while(n <<= 1) { 1872acd5a47SCraig Topper; i--; 1882acd5a47SCraig Topper; } 1892acd5a47SCraig Topper; return i; 1902acd5a47SCraig Topper; } 1912acd5a47SCraig Topper; 1922acd5a47SCraig Topperdefine i32 @cttz_shl_decrement(i32 %n) { 1932acd5a47SCraig Topper; ALL-LABEL: @cttz_shl_decrement( 1942acd5a47SCraig Topper; ALL-NEXT: entry: 19525067f17SCraig Topper; ALL-NEXT: [[TMP0:%.*]] = shl i32 [[N:%.*]], 1 19625067f17SCraig Topper; ALL-NEXT: [[TMP1:%.*]] = call i32 @llvm.cttz.i32(i32 [[TMP0]], i1 false) 19725067f17SCraig Topper; ALL-NEXT: [[TMP2:%.*]] = sub i32 32, [[TMP1]] 19825067f17SCraig Topper; ALL-NEXT: [[TMP3:%.*]] = add i32 [[TMP2]], 1 19925067f17SCraig Topper; ALL-NEXT: [[TMP4:%.*]] = sub i32 31, [[TMP2]] 2002acd5a47SCraig Topper; ALL-NEXT: br label [[WHILE_COND:%.*]] 2012acd5a47SCraig Topper; ALL: while.cond: 20225067f17SCraig Topper; ALL-NEXT: [[TCPHI:%.*]] = phi i32 [ [[TMP3]], [[ENTRY:%.*]] ], [ [[TCDEC:%.*]], [[WHILE_COND]] ] 20325067f17SCraig Topper; ALL-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[SHL:%.*]], [[WHILE_COND]] ] 2042acd5a47SCraig Topper; ALL-NEXT: [[I_0:%.*]] = phi i32 [ 31, [[ENTRY]] ], [ [[INC:%.*]], [[WHILE_COND]] ] 2052acd5a47SCraig Topper; ALL-NEXT: [[SHL]] = shl i32 [[N_ADDR_0]], 1 20625067f17SCraig Topper; ALL-NEXT: [[TCDEC]] = sub nsw i32 [[TCPHI]], 1 20725067f17SCraig Topper; ALL-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TCDEC]], 0 2082acd5a47SCraig Topper; ALL-NEXT: [[INC]] = add nsw i32 [[I_0]], -1 2092acd5a47SCraig Topper; ALL-NEXT: br i1 [[TOBOOL]], label [[WHILE_END:%.*]], label [[WHILE_COND]] 2102acd5a47SCraig Topper; ALL: while.end: 21125067f17SCraig Topper; ALL-NEXT: [[I_0_LCSSA:%.*]] = phi i32 [ [[TMP4]], [[WHILE_COND]] ] 2122acd5a47SCraig Topper; ALL-NEXT: ret i32 [[I_0_LCSSA]] 2132acd5a47SCraig Topper; 2142acd5a47SCraig Topperentry: 2152acd5a47SCraig Topper br label %while.cond 2162acd5a47SCraig Topper 2172acd5a47SCraig Topperwhile.cond: ; preds = %while.cond, %entry 2182acd5a47SCraig Topper %n.addr.0 = phi i32 [ %n, %entry ], [ %shl, %while.cond ] 2192acd5a47SCraig Topper %i.0 = phi i32 [ 31, %entry ], [ %inc, %while.cond ] 2202acd5a47SCraig Topper %shl = shl i32 %n.addr.0, 1 2212acd5a47SCraig Topper %tobool = icmp eq i32 %shl, 0 2222acd5a47SCraig Topper %inc = add nsw i32 %i.0, -1 2232acd5a47SCraig Topper br i1 %tobool, label %while.end, label %while.cond 2242acd5a47SCraig Topper 2252acd5a47SCraig Topperwhile.end: ; preds = %while.cond 2262acd5a47SCraig Topper ret i32 %i.0 2272acd5a47SCraig Topper} 228