1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -codegenprepare < %s | FileCheck %s --check-prefix=SLOW 3; RUN: opt -S -codegenprepare -mattr=+bmi < %s | FileCheck %s --check-prefix=FAST_TZ 4; RUN: opt -S -codegenprepare -mattr=+lzcnt < %s | FileCheck %s --check-prefix=FAST_LZ 5 6target triple = "x86_64-unknown-unknown" 7target datalayout = "e-n32:64" 8 9; If the intrinsic is cheap, nothing should change. 10; If the intrinsic is expensive, check if the input is zero to avoid the call. 11; This is undoing speculation that may have been created by SimplifyCFG + InstCombine. 12 13define i64 @cttz(i64 %A) { 14; SLOW-LABEL: @cttz( 15; SLOW-NEXT: entry: 16; SLOW-NEXT: [[A_FR:%.*]] = freeze i64 [[A:%.*]] 17; SLOW-NEXT: [[CMPZ:%.*]] = icmp eq i64 [[A_FR]], 0 18; SLOW-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 19; SLOW: cond.false: 20; SLOW-NEXT: [[Z:%.*]] = call i64 @llvm.cttz.i64(i64 [[A_FR]], i1 true) 21; SLOW-NEXT: br label [[COND_END]] 22; SLOW: cond.end: 23; SLOW-NEXT: [[CTZ:%.*]] = phi i64 [ 64, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ] 24; SLOW-NEXT: ret i64 [[CTZ]] 25; 26; FAST_TZ-LABEL: @cttz( 27; FAST_TZ-NEXT: entry: 28; FAST_TZ-NEXT: [[Z:%.*]] = call i64 @llvm.cttz.i64(i64 [[A:%.*]], i1 false) 29; FAST_TZ-NEXT: ret i64 [[Z]] 30; 31; FAST_LZ-LABEL: @cttz( 32; FAST_LZ-NEXT: entry: 33; FAST_LZ-NEXT: [[A_FR:%.*]] = freeze i64 [[A:%.*]] 34; FAST_LZ-NEXT: [[CMPZ:%.*]] = icmp eq i64 [[A_FR]], 0 35; FAST_LZ-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 36; FAST_LZ: cond.false: 37; FAST_LZ-NEXT: [[Z:%.*]] = call i64 @llvm.cttz.i64(i64 [[A_FR]], i1 true) 38; FAST_LZ-NEXT: br label [[COND_END]] 39; FAST_LZ: cond.end: 40; FAST_LZ-NEXT: [[CTZ:%.*]] = phi i64 [ 64, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ] 41; FAST_LZ-NEXT: ret i64 [[CTZ]] 42; 43entry: 44 %z = call i64 @llvm.cttz.i64(i64 %A, i1 false) 45 ret i64 %z 46} 47 48define i64 @ctlz(i64 %A) { 49; SLOW-LABEL: @ctlz( 50; SLOW-NEXT: entry: 51; SLOW-NEXT: [[A_FR:%.*]] = freeze i64 [[A:%.*]] 52; SLOW-NEXT: [[CMPZ:%.*]] = icmp eq i64 [[A_FR]], 0 53; SLOW-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 54; SLOW: cond.false: 55; SLOW-NEXT: [[Z:%.*]] = call i64 @llvm.ctlz.i64(i64 [[A_FR]], i1 true) 56; SLOW-NEXT: br label [[COND_END]] 57; SLOW: cond.end: 58; SLOW-NEXT: [[CTZ:%.*]] = phi i64 [ 64, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ] 59; SLOW-NEXT: ret i64 [[CTZ]] 60; 61; FAST_TZ-LABEL: @ctlz( 62; FAST_TZ-NEXT: entry: 63; FAST_TZ-NEXT: [[A_FR:%.*]] = freeze i64 [[A:%.*]] 64; FAST_TZ-NEXT: [[CMPZ:%.*]] = icmp eq i64 [[A_FR]], 0 65; FAST_TZ-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 66; FAST_TZ: cond.false: 67; FAST_TZ-NEXT: [[Z:%.*]] = call i64 @llvm.ctlz.i64(i64 [[A_FR]], i1 true) 68; FAST_TZ-NEXT: br label [[COND_END]] 69; FAST_TZ: cond.end: 70; FAST_TZ-NEXT: [[CTZ:%.*]] = phi i64 [ 64, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ] 71; FAST_TZ-NEXT: ret i64 [[CTZ]] 72; 73; FAST_LZ-LABEL: @ctlz( 74; FAST_LZ-NEXT: entry: 75; FAST_LZ-NEXT: [[Z:%.*]] = call i64 @llvm.ctlz.i64(i64 [[A:%.*]], i1 false) 76; FAST_LZ-NEXT: ret i64 [[Z]] 77; 78entry: 79 %z = call i64 @llvm.ctlz.i64(i64 %A, i1 false) 80 ret i64 %z 81} 82 83declare i64 @llvm.cttz.i64(i64, i1) 84declare i64 @llvm.ctlz.i64(i64, i1) 85 86