1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare i8 @llvm.fshl.i8(i8, i8, i8) 5declare i8 @llvm.fshr.i8(i8, i8, i8) 6declare <2 x i5> @llvm.fshl.v2i5(<2 x i5>, <2 x i5>, <2 x i5>) 7declare void @use(i8) 8 9define i1 @rotl_eq_0(i8 %x, i8 %y) { 10; CHECK-LABEL: @rotl_eq_0( 11; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], 0 12; CHECK-NEXT: ret i1 [[R]] 13; 14 %rot = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %y) 15 %r = icmp eq i8 %rot, 0 16 ret i1 %r 17} 18 19; Extra use is ok. 20 21define i1 @rotl_ne_0(i8 %x, i8 %y) { 22; CHECK-LABEL: @rotl_ne_0( 23; CHECK-NEXT: [[ROT:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Y:%.*]]) 24; CHECK-NEXT: call void @use(i8 [[ROT]]) 25; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X]], 0 26; CHECK-NEXT: ret i1 [[R]] 27; 28 %rot = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %y) 29 call void @use(i8 %rot) 30 %r = icmp ne i8 %rot, 0 31 ret i1 %r 32} 33 34define i1 @rotl_eq_n1(i8 %x, i8 %y) { 35; CHECK-LABEL: @rotl_eq_n1( 36; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], -1 37; CHECK-NEXT: ret i1 [[R]] 38; 39 %rot = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %y) 40 %r = icmp eq i8 %rot, -1 41 ret i1 %r 42} 43 44; Vectors work too. 45 46define <2 x i1> @rotl_ne_n1(<2 x i5> %x, <2 x i5> %y) { 47; CHECK-LABEL: @rotl_ne_n1( 48; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i5> [[X:%.*]], splat (i5 -1) 49; CHECK-NEXT: ret <2 x i1> [[R]] 50; 51 %rot = tail call <2 x i5> @llvm.fshl.v2i5(<2 x i5>%x, <2 x i5> %x, <2 x i5> %y) 52 %r = icmp ne <2 x i5> %rot, <i5 -1, i5 -1> 53 ret <2 x i1> %r 54} 55 56define <2 x i1> @rotl_ne_n1_poison(<2 x i5> %x, <2 x i5> %y) { 57; CHECK-LABEL: @rotl_ne_n1_poison( 58; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i5> [[X:%.*]], <i5 -1, i5 poison> 59; CHECK-NEXT: ret <2 x i1> [[R]] 60; 61 %rot = tail call <2 x i5> @llvm.fshl.v2i5(<2 x i5>%x, <2 x i5> %x, <2 x i5> %y) 62 %r = icmp ne <2 x i5> %rot, <i5 -1, i5 poison> 63 ret <2 x i1> %r 64} 65 66define <2 x i1> @rotl_eq_0_poison(<2 x i5> %x, <2 x i5> %y) { 67; CHECK-LABEL: @rotl_eq_0_poison( 68; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i5> [[X:%.*]], <i5 0, i5 poison> 69; CHECK-NEXT: ret <2 x i1> [[R]] 70; 71 %rot = tail call <2 x i5> @llvm.fshl.v2i5(<2 x i5>%x, <2 x i5> %x, <2 x i5> %y) 72 %r = icmp eq <2 x i5> %rot, <i5 0, i5 poison> 73 ret <2 x i1> %r 74} 75 76; negative test - wrong constant value 77 78define <2 x i1> @rotl_eq_1_poison(<2 x i5> %x, <2 x i5> %y) { 79; CHECK-LABEL: @rotl_eq_1_poison( 80; CHECK-NEXT: [[ROT:%.*]] = tail call <2 x i5> @llvm.fshl.v2i5(<2 x i5> [[X:%.*]], <2 x i5> [[X]], <2 x i5> [[Y:%.*]]) 81; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i5> [[ROT]], <i5 poison, i5 1> 82; CHECK-NEXT: ret <2 x i1> [[R]] 83; 84 %rot = tail call <2 x i5> @llvm.fshl.v2i5(<2 x i5>%x, <2 x i5> %x, <2 x i5> %y) 85 %r = icmp eq <2 x i5> %rot, <i5 poison, i5 1> 86 ret <2 x i1> %r 87} 88 89; negative test - wrong predicate 90 91define <2 x i1> @rotl_sgt_0_poison(<2 x i5> %x, <2 x i5> %y) { 92; CHECK-LABEL: @rotl_sgt_0_poison( 93; CHECK-NEXT: [[ROT:%.*]] = tail call <2 x i5> @llvm.fshl.v2i5(<2 x i5> [[X:%.*]], <2 x i5> [[X]], <2 x i5> [[Y:%.*]]) 94; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i5> [[ROT]], <i5 0, i5 poison> 95; CHECK-NEXT: ret <2 x i1> [[R]] 96; 97 %rot = tail call <2 x i5> @llvm.fshl.v2i5(<2 x i5>%x, <2 x i5> %x, <2 x i5> %y) 98 %r = icmp sgt <2 x i5> %rot, <i5 0, i5 poison> 99 ret <2 x i1> %r 100} 101 102define i1 @rotr_eq_0(i8 %x, i8 %y) { 103; CHECK-LABEL: @rotr_eq_0( 104; CHECK-NEXT: [[ROT:%.*]] = tail call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Y:%.*]]) 105; CHECK-NEXT: call void @use(i8 [[ROT]]) 106; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], 0 107; CHECK-NEXT: ret i1 [[R]] 108; 109 %rot = tail call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 %y) 110 call void @use(i8 %rot) 111 %r = icmp eq i8 %rot, 0 112 ret i1 %r 113} 114 115define i1 @rotr_ne_0(i8 %x, i8 %y) { 116; CHECK-LABEL: @rotr_ne_0( 117; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], 0 118; CHECK-NEXT: ret i1 [[R]] 119; 120 %rot = tail call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 %y) 121 %r = icmp ne i8 %rot, 0 122 ret i1 %r 123} 124 125define i1 @rotr_eq_n1(i8 %x, i8 %y) { 126; CHECK-LABEL: @rotr_eq_n1( 127; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], -1 128; CHECK-NEXT: ret i1 [[R]] 129; 130 %rot = tail call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 %y) 131 %r = icmp eq i8 %rot, -1 132 ret i1 %r 133} 134 135define i1 @rotr_ne_n1(i8 %x, i8 %y) { 136; CHECK-LABEL: @rotr_ne_n1( 137; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], -1 138; CHECK-NEXT: ret i1 [[R]] 139; 140 %rot = tail call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 %y) 141 %r = icmp ne i8 %rot, -1 142 ret i1 %r 143} 144 145; negative test - wrong constant value 146 147define i1 @rotr_ne_1(i8 %x, i8 %y) { 148; CHECK-LABEL: @rotr_ne_1( 149; CHECK-NEXT: [[ROT:%.*]] = tail call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Y:%.*]]) 150; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[ROT]], 1 151; CHECK-NEXT: ret i1 [[R]] 152; 153 %rot = tail call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 %y) 154 %r = icmp ne i8 %rot, 1 155 ret i1 %r 156} 157 158; negative test - wrong predicate 159 160define i1 @rotr_sgt_n1(i8 %x, i8 %y) { 161; CHECK-LABEL: @rotr_sgt_n1( 162; CHECK-NEXT: [[ROT:%.*]] = tail call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Y:%.*]]) 163; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[ROT]], -1 164; CHECK-NEXT: ret i1 [[R]] 165; 166 %rot = tail call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 %y) 167 %r = icmp sgt i8 %rot, -1 168 ret i1 %r 169} 170 171; negative test - must be a rotate, not general funnel shift 172 173define i1 @fshr_sgt_n1(i8 %x, i8 %y, i8 %z) { 174; CHECK-LABEL: @fshr_sgt_n1( 175; CHECK-NEXT: [[FSH:%.*]] = tail call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) 176; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[FSH]], -1 177; CHECK-NEXT: ret i1 [[R]] 178; 179 %fsh = tail call i8 @llvm.fshr.i8(i8 %x, i8 %y, i8 %z) 180 %r = icmp eq i8 %fsh, -1 181 ret i1 %r 182} 183