1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" 5 6; Canonicalize rotate by constant to funnel shift intrinsics. 7; This should help cost modeling for vectorization, inlining, etc. 8; If a target does not have a rotate instruction, the expansion will 9; be exactly these same 3 basic ops (shl/lshr/or). 10 11define i32 @rotl_i32_constant(i32 %x) { 12; CHECK-LABEL: @rotl_i32_constant( 13; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 11) 14; CHECK-NEXT: ret i32 [[R]] 15; 16 %shl = shl i32 %x, 11 17 %shr = lshr i32 %x, 21 18 %r = or i32 %shr, %shl 19 ret i32 %r 20} 21 22define i42 @rotr_i42_constant(i42 %x) { 23; CHECK-LABEL: @rotr_i42_constant( 24; CHECK-NEXT: [[R:%.*]] = call i42 @llvm.fshl.i42(i42 [[X:%.*]], i42 [[X]], i42 31) 25; CHECK-NEXT: ret i42 [[R]] 26; 27 %shl = shl i42 %x, 31 28 %shr = lshr i42 %x, 11 29 %r = or i42 %shr, %shl 30 ret i42 %r 31} 32 33define i8 @rotr_i8_constant_commute(i8 %x) { 34; CHECK-LABEL: @rotr_i8_constant_commute( 35; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 5) 36; CHECK-NEXT: ret i8 [[R]] 37; 38 %shl = shl i8 %x, 5 39 %shr = lshr i8 %x, 3 40 %r = or i8 %shl, %shr 41 ret i8 %r 42} 43 44define i88 @rotl_i88_constant_commute(i88 %x) { 45; CHECK-LABEL: @rotl_i88_constant_commute( 46; CHECK-NEXT: [[R:%.*]] = call i88 @llvm.fshl.i88(i88 [[X:%.*]], i88 [[X]], i88 44) 47; CHECK-NEXT: ret i88 [[R]] 48; 49 %shl = shl i88 %x, 44 50 %shr = lshr i88 %x, 44 51 %r = or i88 %shl, %shr 52 ret i88 %r 53} 54 55; Vector types are allowed. 56 57define <2 x i16> @rotl_v2i16_constant_splat(<2 x i16> %x) { 58; CHECK-LABEL: @rotl_v2i16_constant_splat( 59; CHECK-NEXT: [[R:%.*]] = call <2 x i16> @llvm.fshl.v2i16(<2 x i16> [[X:%.*]], <2 x i16> [[X]], <2 x i16> <i16 1, i16 1>) 60; CHECK-NEXT: ret <2 x i16> [[R]] 61; 62 %shl = shl <2 x i16> %x, <i16 1, i16 1> 63 %shr = lshr <2 x i16> %x, <i16 15, i16 15> 64 %r = or <2 x i16> %shl, %shr 65 ret <2 x i16> %r 66} 67 68define <2 x i16> @rotl_v2i16_constant_splat_undef0(<2 x i16> %x) { 69; CHECK-LABEL: @rotl_v2i16_constant_splat_undef0( 70; CHECK-NEXT: [[R:%.*]] = call <2 x i16> @llvm.fshl.v2i16(<2 x i16> [[X:%.*]], <2 x i16> [[X]], <2 x i16> <i16 1, i16 1>) 71; CHECK-NEXT: ret <2 x i16> [[R]] 72; 73 %shl = shl <2 x i16> %x, <i16 undef, i16 1> 74 %shr = lshr <2 x i16> %x, <i16 15, i16 15> 75 %r = or <2 x i16> %shl, %shr 76 ret <2 x i16> %r 77} 78 79define <2 x i16> @rotl_v2i16_constant_splat_undef1(<2 x i16> %x) { 80; CHECK-LABEL: @rotl_v2i16_constant_splat_undef1( 81; CHECK-NEXT: [[R:%.*]] = call <2 x i16> @llvm.fshl.v2i16(<2 x i16> [[X:%.*]], <2 x i16> [[X]], <2 x i16> <i16 1, i16 1>) 82; CHECK-NEXT: ret <2 x i16> [[R]] 83; 84 %shl = shl <2 x i16> %x, <i16 1, i16 1> 85 %shr = lshr <2 x i16> %x, <i16 15, i16 undef> 86 %r = or <2 x i16> %shl, %shr 87 ret <2 x i16> %r 88} 89 90; Non-power-of-2 vector types are allowed. 91 92define <2 x i17> @rotr_v2i17_constant_splat(<2 x i17> %x) { 93; CHECK-LABEL: @rotr_v2i17_constant_splat( 94; CHECK-NEXT: [[R:%.*]] = call <2 x i17> @llvm.fshl.v2i17(<2 x i17> [[X:%.*]], <2 x i17> [[X]], <2 x i17> <i17 12, i17 12>) 95; CHECK-NEXT: ret <2 x i17> [[R]] 96; 97 %shl = shl <2 x i17> %x, <i17 12, i17 12> 98 %shr = lshr <2 x i17> %x, <i17 5, i17 5> 99 %r = or <2 x i17> %shr, %shl 100 ret <2 x i17> %r 101} 102 103define <2 x i17> @rotr_v2i17_constant_splat_undef0(<2 x i17> %x) { 104; CHECK-LABEL: @rotr_v2i17_constant_splat_undef0( 105; CHECK-NEXT: [[R:%.*]] = call <2 x i17> @llvm.fshl.v2i17(<2 x i17> [[X:%.*]], <2 x i17> [[X]], <2 x i17> <i17 12, i17 12>) 106; CHECK-NEXT: ret <2 x i17> [[R]] 107; 108 %shl = shl <2 x i17> %x, <i17 12, i17 undef> 109 %shr = lshr <2 x i17> %x, <i17 undef, i17 5> 110 %r = or <2 x i17> %shr, %shl 111 ret <2 x i17> %r 112} 113 114define <2 x i17> @rotr_v2i17_constant_splat_undef1(<2 x i17> %x) { 115; CHECK-LABEL: @rotr_v2i17_constant_splat_undef1( 116; CHECK-NEXT: [[R:%.*]] = call <2 x i17> @llvm.fshl.v2i17(<2 x i17> [[X:%.*]], <2 x i17> [[X]], <2 x i17> <i17 12, i17 12>) 117; CHECK-NEXT: ret <2 x i17> [[R]] 118; 119 %shl = shl <2 x i17> %x, <i17 12, i17 undef> 120 %shr = lshr <2 x i17> %x, <i17 5, i17 undef> 121 %r = or <2 x i17> %shr, %shl 122 ret <2 x i17> %r 123} 124 125; Allow arbitrary shift constants. 126; Support undef elements. 127 128define <2 x i32> @rotr_v2i32_constant_nonsplat(<2 x i32> %x) { 129; CHECK-LABEL: @rotr_v2i32_constant_nonsplat( 130; CHECK-NEXT: [[R:%.*]] = call <2 x i32> @llvm.fshl.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[X]], <2 x i32> <i32 17, i32 19>) 131; CHECK-NEXT: ret <2 x i32> [[R]] 132; 133 %shl = shl <2 x i32> %x, <i32 17, i32 19> 134 %shr = lshr <2 x i32> %x, <i32 15, i32 13> 135 %r = or <2 x i32> %shl, %shr 136 ret <2 x i32> %r 137} 138 139define <2 x i32> @rotr_v2i32_constant_nonsplat_undef0(<2 x i32> %x) { 140; CHECK-LABEL: @rotr_v2i32_constant_nonsplat_undef0( 141; CHECK-NEXT: [[R:%.*]] = call <2 x i32> @llvm.fshl.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[X]], <2 x i32> <i32 0, i32 19>) 142; CHECK-NEXT: ret <2 x i32> [[R]] 143; 144 %shl = shl <2 x i32> %x, <i32 undef, i32 19> 145 %shr = lshr <2 x i32> %x, <i32 15, i32 13> 146 %r = or <2 x i32> %shl, %shr 147 ret <2 x i32> %r 148} 149 150define <2 x i32> @rotr_v2i32_constant_nonsplat_undef1(<2 x i32> %x) { 151; CHECK-LABEL: @rotr_v2i32_constant_nonsplat_undef1( 152; CHECK-NEXT: [[R:%.*]] = call <2 x i32> @llvm.fshl.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[X]], <2 x i32> <i32 17, i32 0>) 153; CHECK-NEXT: ret <2 x i32> [[R]] 154; 155 %shl = shl <2 x i32> %x, <i32 17, i32 19> 156 %shr = lshr <2 x i32> %x, <i32 15, i32 undef> 157 %r = or <2 x i32> %shl, %shr 158 ret <2 x i32> %r 159} 160 161define <2 x i36> @rotl_v2i36_constant_nonsplat(<2 x i36> %x) { 162; CHECK-LABEL: @rotl_v2i36_constant_nonsplat( 163; CHECK-NEXT: [[R:%.*]] = call <2 x i36> @llvm.fshl.v2i36(<2 x i36> [[X:%.*]], <2 x i36> [[X]], <2 x i36> <i36 21, i36 11>) 164; CHECK-NEXT: ret <2 x i36> [[R]] 165; 166 %shl = shl <2 x i36> %x, <i36 21, i36 11> 167 %shr = lshr <2 x i36> %x, <i36 15, i36 25> 168 %r = or <2 x i36> %shl, %shr 169 ret <2 x i36> %r 170} 171 172define <3 x i36> @rotl_v3i36_constant_nonsplat_undef0(<3 x i36> %x) { 173; CHECK-LABEL: @rotl_v3i36_constant_nonsplat_undef0( 174; CHECK-NEXT: [[R:%.*]] = call <3 x i36> @llvm.fshl.v3i36(<3 x i36> [[X:%.*]], <3 x i36> [[X]], <3 x i36> <i36 21, i36 11, i36 0>) 175; CHECK-NEXT: ret <3 x i36> [[R]] 176; 177 %shl = shl <3 x i36> %x, <i36 21, i36 11, i36 undef> 178 %shr = lshr <3 x i36> %x, <i36 15, i36 25, i36 undef> 179 %r = or <3 x i36> %shl, %shr 180 ret <3 x i36> %r 181} 182 183; The most basic rotate by variable - no guards for UB due to oversized shifts. 184; This cannot be canonicalized to funnel shift target-independently. The safe 185; expansion includes masking for the shift amount that is not included here, 186; so it could be more expensive. 187 188define i32 @rotl_i32(i32 %x, i32 %y) { 189; CHECK-LABEL: @rotl_i32( 190; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[Y:%.*]] 191; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], [[Y]] 192; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X]], [[SUB]] 193; CHECK-NEXT: [[R:%.*]] = or i32 [[SHR]], [[SHL]] 194; CHECK-NEXT: ret i32 [[R]] 195; 196 %sub = sub i32 32, %y 197 %shl = shl i32 %x, %y 198 %shr = lshr i32 %x, %sub 199 %r = or i32 %shr, %shl 200 ret i32 %r 201} 202 203; Non-power-of-2 types should follow the same reasoning. Left/right is determined by subtract. 204 205define i37 @rotr_i37(i37 %x, i37 %y) { 206; CHECK-LABEL: @rotr_i37( 207; CHECK-NEXT: [[SUB:%.*]] = sub i37 37, [[Y:%.*]] 208; CHECK-NEXT: [[SHL:%.*]] = shl i37 [[X:%.*]], [[SUB]] 209; CHECK-NEXT: [[SHR:%.*]] = lshr i37 [[X]], [[Y]] 210; CHECK-NEXT: [[R:%.*]] = or i37 [[SHR]], [[SHL]] 211; CHECK-NEXT: ret i37 [[R]] 212; 213 %sub = sub i37 37, %y 214 %shl = shl i37 %x, %sub 215 %shr = lshr i37 %x, %y 216 %r = or i37 %shr, %shl 217 ret i37 %r 218} 219 220; Commute 'or' operands. 221 222define i8 @rotr_i8_commute(i8 %x, i8 %y) { 223; CHECK-LABEL: @rotr_i8_commute( 224; CHECK-NEXT: [[SUB:%.*]] = sub i8 8, [[Y:%.*]] 225; CHECK-NEXT: [[SHL:%.*]] = shl i8 [[X:%.*]], [[SUB]] 226; CHECK-NEXT: [[SHR:%.*]] = lshr i8 [[X]], [[Y]] 227; CHECK-NEXT: [[R:%.*]] = or i8 [[SHL]], [[SHR]] 228; CHECK-NEXT: ret i8 [[R]] 229; 230 %sub = sub i8 8, %y 231 %shl = shl i8 %x, %sub 232 %shr = lshr i8 %x, %y 233 %r = or i8 %shl, %shr 234 ret i8 %r 235} 236 237; Vector types should follow the same rules. 238 239define <4 x i32> @rotl_v4i32(<4 x i32> %x, <4 x i32> %y) { 240; CHECK-LABEL: @rotl_v4i32( 241; CHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> <i32 32, i32 32, i32 32, i32 32>, [[Y:%.*]] 242; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y]] 243; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], [[SUB]] 244; CHECK-NEXT: [[R:%.*]] = or <4 x i32> [[SHL]], [[SHR]] 245; CHECK-NEXT: ret <4 x i32> [[R]] 246; 247 %sub = sub <4 x i32> <i32 32, i32 32, i32 32, i32 32>, %y 248 %shl = shl <4 x i32> %x, %y 249 %shr = lshr <4 x i32> %x, %sub 250 %r = or <4 x i32> %shl, %shr 251 ret <4 x i32> %r 252} 253 254; Non-power-of-2 vector types should follow the same rules. 255 256define <3 x i42> @rotr_v3i42(<3 x i42> %x, <3 x i42> %y) { 257; CHECK-LABEL: @rotr_v3i42( 258; CHECK-NEXT: [[SUB:%.*]] = sub <3 x i42> <i42 42, i42 42, i42 42>, [[Y:%.*]] 259; CHECK-NEXT: [[SHL:%.*]] = shl <3 x i42> [[X:%.*]], [[SUB]] 260; CHECK-NEXT: [[SHR:%.*]] = lshr <3 x i42> [[X]], [[Y]] 261; CHECK-NEXT: [[R:%.*]] = or <3 x i42> [[SHR]], [[SHL]] 262; CHECK-NEXT: ret <3 x i42> [[R]] 263; 264 %sub = sub <3 x i42> <i42 42, i42 42, i42 42>, %y 265 %shl = shl <3 x i42> %x, %sub 266 %shr = lshr <3 x i42> %x, %y 267 %r = or <3 x i42> %shr, %shl 268 ret <3 x i42> %r 269} 270 271; This is the canonical pattern for a UB-safe rotate-by-variable with power-of-2-size scalar type. 272; The backend expansion of funnel shift for targets that don't have a rotate instruction should 273; match the original IR, so it is always good to canonicalize to the intrinsics for this pattern. 274 275define i32 @rotl_safe_i32(i32 %x, i32 %y) { 276; CHECK-LABEL: @rotl_safe_i32( 277; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]]) 278; CHECK-NEXT: ret i32 [[R]] 279; 280 %negy = sub i32 0, %y 281 %ymask = and i32 %y, 31 282 %negymask = and i32 %negy, 31 283 %shl = shl i32 %x, %ymask 284 %shr = lshr i32 %x, %negymask 285 %r = or i32 %shr, %shl 286 ret i32 %r 287} 288 289; Extra uses don't change anything. 290 291define i16 @rotl_safe_i16_commute_extra_use(i16 %x, i16 %y, i16* %p) { 292; CHECK-LABEL: @rotl_safe_i16_commute_extra_use( 293; CHECK-NEXT: [[NEGY:%.*]] = sub i16 0, [[Y:%.*]] 294; CHECK-NEXT: [[NEGYMASK:%.*]] = and i16 [[NEGY]], 15 295; CHECK-NEXT: store i16 [[NEGYMASK]], i16* [[P:%.*]], align 2 296; CHECK-NEXT: [[R:%.*]] = call i16 @llvm.fshl.i16(i16 [[X:%.*]], i16 [[X]], i16 [[Y]]) 297; CHECK-NEXT: ret i16 [[R]] 298; 299 %negy = sub i16 0, %y 300 %ymask = and i16 %y, 15 301 %negymask = and i16 %negy, 15 302 store i16 %negymask, i16* %p 303 %shl = shl i16 %x, %ymask 304 %shr = lshr i16 %x, %negymask 305 %r = or i16 %shl, %shr 306 ret i16 %r 307} 308 309; Left/right is determined by the negation. 310 311define i64 @rotr_safe_i64(i64 %x, i64 %y) { 312; CHECK-LABEL: @rotr_safe_i64( 313; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Y:%.*]]) 314; CHECK-NEXT: ret i64 [[R]] 315; 316 %negy = sub i64 0, %y 317 %ymask = and i64 %y, 63 318 %negymask = and i64 %negy, 63 319 %shl = shl i64 %x, %negymask 320 %shr = lshr i64 %x, %ymask 321 %r = or i64 %shr, %shl 322 ret i64 %r 323} 324 325; Extra uses don't change anything. 326 327define i8 @rotr_safe_i8_commute_extra_use(i8 %x, i8 %y, i8* %p) { 328; CHECK-LABEL: @rotr_safe_i8_commute_extra_use( 329; CHECK-NEXT: [[NEGY:%.*]] = sub i8 0, [[Y:%.*]] 330; CHECK-NEXT: [[YMASK:%.*]] = and i8 [[Y]], 7 331; CHECK-NEXT: [[NEGYMASK:%.*]] = and i8 [[NEGY]], 7 332; CHECK-NEXT: [[SHL:%.*]] = shl i8 [[X:%.*]], [[NEGYMASK]] 333; CHECK-NEXT: [[SHR:%.*]] = lshr i8 [[X]], [[YMASK]] 334; CHECK-NEXT: store i8 [[SHR]], i8* [[P:%.*]], align 1 335; CHECK-NEXT: [[R:%.*]] = or i8 [[SHL]], [[SHR]] 336; CHECK-NEXT: ret i8 [[R]] 337; 338 %negy = sub i8 0, %y 339 %ymask = and i8 %y, 7 340 %negymask = and i8 %negy, 7 341 %shl = shl i8 %x, %negymask 342 %shr = lshr i8 %x, %ymask 343 store i8 %shr, i8* %p 344 %r = or i8 %shl, %shr 345 ret i8 %r 346} 347 348; Vectors follow the same rules. 349 350define <2 x i32> @rotl_safe_v2i32(<2 x i32> %x, <2 x i32> %y) { 351; CHECK-LABEL: @rotl_safe_v2i32( 352; CHECK-NEXT: [[R:%.*]] = call <2 x i32> @llvm.fshl.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[X]], <2 x i32> [[Y:%.*]]) 353; CHECK-NEXT: ret <2 x i32> [[R]] 354; 355 %negy = sub <2 x i32> zeroinitializer, %y 356 %ymask = and <2 x i32> %y, <i32 31, i32 31> 357 %negymask = and <2 x i32> %negy, <i32 31, i32 31> 358 %shl = shl <2 x i32> %x, %ymask 359 %shr = lshr <2 x i32> %x, %negymask 360 %r = or <2 x i32> %shr, %shl 361 ret <2 x i32> %r 362} 363 364; Vectors follow the same rules. 365 366define <3 x i16> @rotr_safe_v3i16(<3 x i16> %x, <3 x i16> %y) { 367; CHECK-LABEL: @rotr_safe_v3i16( 368; CHECK-NEXT: [[R:%.*]] = call <3 x i16> @llvm.fshr.v3i16(<3 x i16> [[X:%.*]], <3 x i16> [[X]], <3 x i16> [[Y:%.*]]) 369; CHECK-NEXT: ret <3 x i16> [[R]] 370; 371 %negy = sub <3 x i16> zeroinitializer, %y 372 %ymask = and <3 x i16> %y, <i16 15, i16 15, i16 15> 373 %negymask = and <3 x i16> %negy, <i16 15, i16 15, i16 15> 374 %shl = shl <3 x i16> %x, %negymask 375 %shr = lshr <3 x i16> %x, %ymask 376 %r = or <3 x i16> %shr, %shl 377 ret <3 x i16> %r 378} 379 380; These are optionally UB-free rotate left/right patterns that are narrowed to a smaller bitwidth. 381; See PR34046, PR16726, and PR39624 for motivating examples: 382; https://bugs.llvm.org/show_bug.cgi?id=34046 383; https://bugs.llvm.org/show_bug.cgi?id=16726 384; https://bugs.llvm.org/show_bug.cgi?id=39624 385 386define i16 @rotate_left_16bit(i16 %v, i32 %shift) { 387; CHECK-LABEL: @rotate_left_16bit( 388; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHIFT:%.*]] to i16 389; CHECK-NEXT: [[CONV2:%.*]] = call i16 @llvm.fshl.i16(i16 [[V:%.*]], i16 [[V]], i16 [[TMP1]]) 390; CHECK-NEXT: ret i16 [[CONV2]] 391; 392 %and = and i32 %shift, 15 393 %conv = zext i16 %v to i32 394 %shl = shl i32 %conv, %and 395 %sub = sub i32 16, %and 396 %shr = lshr i32 %conv, %sub 397 %or = or i32 %shr, %shl 398 %conv2 = trunc i32 %or to i16 399 ret i16 %conv2 400} 401 402; Commute the 'or' operands and try a vector type. 403 404define <2 x i16> @rotate_left_commute_16bit_vec(<2 x i16> %v, <2 x i32> %shift) { 405; CHECK-LABEL: @rotate_left_commute_16bit_vec( 406; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[SHIFT:%.*]] to <2 x i16> 407; CHECK-NEXT: [[CONV2:%.*]] = call <2 x i16> @llvm.fshl.v2i16(<2 x i16> [[V:%.*]], <2 x i16> [[V]], <2 x i16> [[TMP1]]) 408; CHECK-NEXT: ret <2 x i16> [[CONV2]] 409; 410 %and = and <2 x i32> %shift, <i32 15, i32 15> 411 %conv = zext <2 x i16> %v to <2 x i32> 412 %shl = shl <2 x i32> %conv, %and 413 %sub = sub <2 x i32> <i32 16, i32 16>, %and 414 %shr = lshr <2 x i32> %conv, %sub 415 %or = or <2 x i32> %shl, %shr 416 %conv2 = trunc <2 x i32> %or to <2 x i16> 417 ret <2 x i16> %conv2 418} 419 420; Change the size, rotation direction (the subtract is on the left-shift), and mask op. 421 422define i8 @rotate_right_8bit(i8 %v, i3 %shift) { 423; CHECK-LABEL: @rotate_right_8bit( 424; CHECK-NEXT: [[TMP1:%.*]] = zext i3 [[SHIFT:%.*]] to i8 425; CHECK-NEXT: [[CONV2:%.*]] = call i8 @llvm.fshr.i8(i8 [[V:%.*]], i8 [[V]], i8 [[TMP1]]) 426; CHECK-NEXT: ret i8 [[CONV2]] 427; 428 %and = zext i3 %shift to i32 429 %conv = zext i8 %v to i32 430 %shr = lshr i32 %conv, %and 431 %sub = sub i32 8, %and 432 %shl = shl i32 %conv, %sub 433 %or = or i32 %shl, %shr 434 %conv2 = trunc i32 %or to i8 435 ret i8 %conv2 436} 437 438; The shifted value does not need to be a zexted value; here it is masked. 439; The shift mask could be less than the bitwidth, but this is still ok. 440 441define i8 @rotate_right_commute_8bit(i32 %v, i32 %shift) { 442; CHECK-LABEL: @rotate_right_commute_8bit( 443; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHIFT:%.*]] to i8 444; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], 3 445; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[V:%.*]] to i8 446; CHECK-NEXT: [[CONV2:%.*]] = call i8 @llvm.fshr.i8(i8 [[TMP3]], i8 [[TMP3]], i8 [[TMP2]]) 447; CHECK-NEXT: ret i8 [[CONV2]] 448; 449 %and = and i32 %shift, 3 450 %conv = and i32 %v, 255 451 %shr = lshr i32 %conv, %and 452 %sub = sub i32 8, %and 453 %shl = shl i32 %conv, %sub 454 %or = or i32 %shr, %shl 455 %conv2 = trunc i32 %or to i8 456 ret i8 %conv2 457} 458 459; If the original source does not mask the shift amount, 460; we still do the transform by adding masks to make it safe. 461 462define i8 @rotate8_not_safe(i8 %v, i32 %shamt) { 463; CHECK-LABEL: @rotate8_not_safe( 464; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHAMT:%.*]] to i8 465; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.fshl.i8(i8 [[V:%.*]], i8 [[V]], i8 [[TMP1]]) 466; CHECK-NEXT: ret i8 [[RET]] 467; 468 %conv = zext i8 %v to i32 469 %sub = sub i32 8, %shamt 470 %shr = lshr i32 %conv, %sub 471 %shl = shl i32 %conv, %shamt 472 %or = or i32 %shr, %shl 473 %ret = trunc i32 %or to i8 474 ret i8 %ret 475} 476 477; A non-power-of-2 destination type can't be masked as above. 478 479define i9 @rotate9_not_safe(i9 %v, i32 %shamt) { 480; CHECK-LABEL: @rotate9_not_safe( 481; CHECK-NEXT: [[CONV:%.*]] = zext i9 [[V:%.*]] to i32 482; CHECK-NEXT: [[SUB:%.*]] = sub i32 9, [[SHAMT:%.*]] 483; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[CONV]], [[SUB]] 484; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[CONV]], [[SHAMT]] 485; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHR]], [[SHL]] 486; CHECK-NEXT: [[RET:%.*]] = trunc i32 [[OR]] to i9 487; CHECK-NEXT: ret i9 [[RET]] 488; 489 %conv = zext i9 %v to i32 490 %sub = sub i32 9, %shamt 491 %shr = lshr i32 %conv, %sub 492 %shl = shl i32 %conv, %shamt 493 %or = or i32 %shr, %shl 494 %ret = trunc i32 %or to i9 495 ret i9 %ret 496} 497 498; We should narrow (v << (s & 15)) | (v >> (-s & 15)) 499; when both v and s have been promoted. 500 501define i16 @rotateleft_16_neg_mask(i16 %v, i16 %shamt) { 502; CHECK-LABEL: @rotateleft_16_neg_mask( 503; CHECK-NEXT: [[OR:%.*]] = call i16 @llvm.fshl.i16(i16 [[V:%.*]], i16 [[V]], i16 [[SHAMT:%.*]]) 504; CHECK-NEXT: ret i16 [[OR]] 505; 506 %neg = sub i16 0, %shamt 507 %lshamt = and i16 %shamt, 15 508 %lshamtconv = zext i16 %lshamt to i32 509 %rshamt = and i16 %neg, 15 510 %rshamtconv = zext i16 %rshamt to i32 511 %conv = zext i16 %v to i32 512 %shl = shl i32 %conv, %lshamtconv 513 %shr = lshr i32 %conv, %rshamtconv 514 %or = or i32 %shr, %shl 515 %ret = trunc i32 %or to i16 516 ret i16 %ret 517} 518 519define i16 @rotateleft_16_neg_mask_commute(i16 %v, i16 %shamt) { 520; CHECK-LABEL: @rotateleft_16_neg_mask_commute( 521; CHECK-NEXT: [[OR:%.*]] = call i16 @llvm.fshl.i16(i16 [[V:%.*]], i16 [[V]], i16 [[SHAMT:%.*]]) 522; CHECK-NEXT: ret i16 [[OR]] 523; 524 %neg = sub i16 0, %shamt 525 %lshamt = and i16 %shamt, 15 526 %lshamtconv = zext i16 %lshamt to i32 527 %rshamt = and i16 %neg, 15 528 %rshamtconv = zext i16 %rshamt to i32 529 %conv = zext i16 %v to i32 530 %shl = shl i32 %conv, %lshamtconv 531 %shr = lshr i32 %conv, %rshamtconv 532 %or = or i32 %shl, %shr 533 %ret = trunc i32 %or to i16 534 ret i16 %ret 535} 536 537define i8 @rotateright_8_neg_mask(i8 %v, i8 %shamt) { 538; CHECK-LABEL: @rotateright_8_neg_mask( 539; CHECK-NEXT: [[OR:%.*]] = call i8 @llvm.fshr.i8(i8 [[V:%.*]], i8 [[V]], i8 [[SHAMT:%.*]]) 540; CHECK-NEXT: ret i8 [[OR]] 541; 542 %neg = sub i8 0, %shamt 543 %rshamt = and i8 %shamt, 7 544 %rshamtconv = zext i8 %rshamt to i32 545 %lshamt = and i8 %neg, 7 546 %lshamtconv = zext i8 %lshamt to i32 547 %conv = zext i8 %v to i32 548 %shl = shl i32 %conv, %lshamtconv 549 %shr = lshr i32 %conv, %rshamtconv 550 %or = or i32 %shr, %shl 551 %ret = trunc i32 %or to i8 552 ret i8 %ret 553} 554 555define i8 @rotateright_8_neg_mask_commute(i8 %v, i8 %shamt) { 556; CHECK-LABEL: @rotateright_8_neg_mask_commute( 557; CHECK-NEXT: [[OR:%.*]] = call i8 @llvm.fshr.i8(i8 [[V:%.*]], i8 [[V]], i8 [[SHAMT:%.*]]) 558; CHECK-NEXT: ret i8 [[OR]] 559; 560 %neg = sub i8 0, %shamt 561 %rshamt = and i8 %shamt, 7 562 %rshamtconv = zext i8 %rshamt to i32 563 %lshamt = and i8 %neg, 7 564 %lshamtconv = zext i8 %lshamt to i32 565 %conv = zext i8 %v to i32 566 %shl = shl i32 %conv, %lshamtconv 567 %shr = lshr i32 %conv, %rshamtconv 568 %or = or i32 %shl, %shr 569 %ret = trunc i32 %or to i8 570 ret i8 %ret 571} 572 573; The shift amount may already be in the wide type, 574; so we need to truncate it going into the rotate pattern. 575 576define i16 @rotateright_16_neg_mask_wide_amount(i16 %v, i32 %shamt) { 577; CHECK-LABEL: @rotateright_16_neg_mask_wide_amount( 578; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHAMT:%.*]] to i16 579; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.fshr.i16(i16 [[V:%.*]], i16 [[V]], i16 [[TMP1]]) 580; CHECK-NEXT: ret i16 [[RET]] 581; 582 %neg = sub i32 0, %shamt 583 %rshamt = and i32 %shamt, 15 584 %lshamt = and i32 %neg, 15 585 %conv = zext i16 %v to i32 586 %shl = shl i32 %conv, %lshamt 587 %shr = lshr i32 %conv, %rshamt 588 %or = or i32 %shr, %shl 589 %ret = trunc i32 %or to i16 590 ret i16 %ret 591} 592 593define i16 @rotateright_16_neg_mask_wide_amount_commute(i16 %v, i32 %shamt) { 594; CHECK-LABEL: @rotateright_16_neg_mask_wide_amount_commute( 595; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHAMT:%.*]] to i16 596; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.fshr.i16(i16 [[V:%.*]], i16 [[V]], i16 [[TMP1]]) 597; CHECK-NEXT: ret i16 [[RET]] 598; 599 %neg = sub i32 0, %shamt 600 %rshamt = and i32 %shamt, 15 601 %lshamt = and i32 %neg, 15 602 %conv = zext i16 %v to i32 603 %shl = shl i32 %conv, %lshamt 604 %shr = lshr i32 %conv, %rshamt 605 %or = or i32 %shl, %shr 606 %ret = trunc i32 %or to i16 607 ret i16 %ret 608} 609 610define i64 @rotateright_64_zext_neg_mask_amount(i64 %0, i32 %1) { 611; CHECK-LABEL: @rotateright_64_zext_neg_mask_amount( 612; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[TMP1:%.*]] to i64 613; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP0:%.*]], i64 [[TMP0]], i64 [[TMP3]]) 614; CHECK-NEXT: ret i64 [[TMP4]] 615; 616 %3 = and i32 %1, 63 617 %4 = zext i32 %3 to i64 618 %5 = lshr i64 %0, %4 619 %6 = sub nsw i32 0, %1 620 %7 = and i32 %6, 63 621 %8 = zext i32 %7 to i64 622 %9 = shl i64 %0, %8 623 %10 = or i64 %5, %9 624 ret i64 %10 625} 626 627define i8 @rotateleft_8_neg_mask_wide_amount(i8 %v, i32 %shamt) { 628; CHECK-LABEL: @rotateleft_8_neg_mask_wide_amount( 629; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHAMT:%.*]] to i8 630; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.fshl.i8(i8 [[V:%.*]], i8 [[V]], i8 [[TMP1]]) 631; CHECK-NEXT: ret i8 [[RET]] 632; 633 %neg = sub i32 0, %shamt 634 %lshamt = and i32 %shamt, 7 635 %rshamt = and i32 %neg, 7 636 %conv = zext i8 %v to i32 637 %shl = shl i32 %conv, %lshamt 638 %shr = lshr i32 %conv, %rshamt 639 %or = or i32 %shr, %shl 640 %ret = trunc i32 %or to i8 641 ret i8 %ret 642} 643 644define i8 @rotateleft_8_neg_mask_wide_amount_commute(i8 %v, i32 %shamt) { 645; CHECK-LABEL: @rotateleft_8_neg_mask_wide_amount_commute( 646; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHAMT:%.*]] to i8 647; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.fshl.i8(i8 [[V:%.*]], i8 [[V]], i8 [[TMP1]]) 648; CHECK-NEXT: ret i8 [[RET]] 649; 650 %neg = sub i32 0, %shamt 651 %lshamt = and i32 %shamt, 7 652 %rshamt = and i32 %neg, 7 653 %conv = zext i8 %v to i32 654 %shl = shl i32 %conv, %lshamt 655 %shr = lshr i32 %conv, %rshamt 656 %or = or i32 %shl, %shr 657 %ret = trunc i32 %or to i8 658 ret i8 %ret 659} 660 661define i64 @rotateleft_64_zext_neg_mask_amount(i64 %0, i32 %1) { 662; CHECK-LABEL: @rotateleft_64_zext_neg_mask_amount( 663; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[TMP1:%.*]] to i64 664; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.fshl.i64(i64 [[TMP0:%.*]], i64 [[TMP0]], i64 [[TMP3]]) 665; CHECK-NEXT: ret i64 [[TMP4]] 666; 667 %3 = and i32 %1, 63 668 %4 = zext i32 %3 to i64 669 %5 = shl i64 %0, %4 670 %6 = sub nsw i32 0, %1 671 %7 = and i32 %6, 63 672 %8 = zext i32 %7 to i64 673 %9 = lshr i64 %0, %8 674 %10 = or i64 %5, %9 675 ret i64 %10 676} 677 678; Non-power-of-2 types. This could be transformed, but it's not a typical rotate pattern. 679 680define i9 @rotateleft_9_neg_mask_wide_amount_commute(i9 %v, i33 %shamt) { 681; CHECK-LABEL: @rotateleft_9_neg_mask_wide_amount_commute( 682; CHECK-NEXT: [[NEG:%.*]] = sub i33 0, [[SHAMT:%.*]] 683; CHECK-NEXT: [[LSHAMT:%.*]] = and i33 [[SHAMT]], 8 684; CHECK-NEXT: [[RSHAMT:%.*]] = and i33 [[NEG]], 8 685; CHECK-NEXT: [[CONV:%.*]] = zext i9 [[V:%.*]] to i33 686; CHECK-NEXT: [[SHL:%.*]] = shl i33 [[CONV]], [[LSHAMT]] 687; CHECK-NEXT: [[SHR:%.*]] = lshr i33 [[CONV]], [[RSHAMT]] 688; CHECK-NEXT: [[OR:%.*]] = or i33 [[SHL]], [[SHR]] 689; CHECK-NEXT: [[RET:%.*]] = trunc i33 [[OR]] to i9 690; CHECK-NEXT: ret i9 [[RET]] 691; 692 %neg = sub i33 0, %shamt 693 %lshamt = and i33 %shamt, 8 694 %rshamt = and i33 %neg, 8 695 %conv = zext i9 %v to i33 696 %shl = shl i33 %conv, %lshamt 697 %shr = lshr i33 %conv, %rshamt 698 %or = or i33 %shl, %shr 699 %ret = trunc i33 %or to i9 700 ret i9 %ret 701} 702 703; Fold or(shl(v,x),lshr(v,bw-x)) iff x < bw 704 705define i64 @rotl_sub_mask(i64 %0, i64 %1) { 706; CHECK-LABEL: @rotl_sub_mask( 707; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.fshl.i64(i64 [[TMP0:%.*]], i64 [[TMP0]], i64 [[TMP1:%.*]]) 708; CHECK-NEXT: ret i64 [[TMP3]] 709; 710 %3 = and i64 %1, 63 711 %4 = shl i64 %0, %3 712 %5 = sub nuw nsw i64 64, %3 713 %6 = lshr i64 %0, %5 714 %7 = or i64 %6, %4 715 ret i64 %7 716} 717 718; Fold or(lshr(v,x),shl(v,bw-x)) iff x < bw 719 720define i64 @rotr_sub_mask(i64 %0, i64 %1) { 721; CHECK-LABEL: @rotr_sub_mask( 722; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP0:%.*]], i64 [[TMP0]], i64 [[TMP1:%.*]]) 723; CHECK-NEXT: ret i64 [[TMP3]] 724; 725 %3 = and i64 %1, 63 726 %4 = lshr i64 %0, %3 727 %5 = sub nuw nsw i64 64, %3 728 %6 = shl i64 %0, %5 729 %7 = or i64 %6, %4 730 ret i64 %7 731} 732 733define <2 x i64> @rotr_sub_mask_vector(<2 x i64> %0, <2 x i64> %1) { 734; CHECK-LABEL: @rotr_sub_mask_vector( 735; CHECK-NEXT: [[TMP3:%.*]] = call <2 x i64> @llvm.fshr.v2i64(<2 x i64> [[TMP0:%.*]], <2 x i64> [[TMP0]], <2 x i64> [[TMP1:%.*]]) 736; CHECK-NEXT: ret <2 x i64> [[TMP3]] 737; 738 %3 = and <2 x i64> %1, <i64 63, i64 63> 739 %4 = lshr <2 x i64> %0, %3 740 %5 = sub nuw nsw <2 x i64> <i64 64, i64 64>, %3 741 %6 = shl <2 x i64> %0, %5 742 %7 = or <2 x i64> %6, %4 743 ret <2 x i64> %7 744} 745 746; Convert select pattern to masked shift that ends in 'or'. 747 748define i32 @rotr_select(i32 %x, i32 %shamt) { 749; CHECK-LABEL: @rotr_select( 750; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[SHAMT:%.*]]) 751; CHECK-NEXT: ret i32 [[R]] 752; 753 %cmp = icmp eq i32 %shamt, 0 754 %sub = sub i32 32, %shamt 755 %shr = lshr i32 %x, %shamt 756 %shl = shl i32 %x, %sub 757 %or = or i32 %shr, %shl 758 %r = select i1 %cmp, i32 %x, i32 %or 759 ret i32 %r 760} 761 762; Convert select pattern to masked shift that ends in 'or'. 763 764define i8 @rotr_select_commute(i8 %x, i8 %shamt) { 765; CHECK-LABEL: @rotr_select_commute( 766; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[SHAMT:%.*]]) 767; CHECK-NEXT: ret i8 [[R]] 768; 769 %cmp = icmp eq i8 %shamt, 0 770 %sub = sub i8 8, %shamt 771 %shr = lshr i8 %x, %shamt 772 %shl = shl i8 %x, %sub 773 %or = or i8 %shl, %shr 774 %r = select i1 %cmp, i8 %x, i8 %or 775 ret i8 %r 776} 777 778; Convert select pattern to masked shift that ends in 'or'. 779 780define i16 @rotl_select(i16 %x, i16 %shamt) { 781; CHECK-LABEL: @rotl_select( 782; CHECK-NEXT: [[R:%.*]] = call i16 @llvm.fshl.i16(i16 [[X:%.*]], i16 [[X]], i16 [[SHAMT:%.*]]) 783; CHECK-NEXT: ret i16 [[R]] 784; 785 %cmp = icmp eq i16 %shamt, 0 786 %sub = sub i16 16, %shamt 787 %shr = lshr i16 %x, %sub 788 %shl = shl i16 %x, %shamt 789 %or = or i16 %shr, %shl 790 %r = select i1 %cmp, i16 %x, i16 %or 791 ret i16 %r 792} 793 794; Convert select pattern to masked shift that ends in 'or'. 795 796define <2 x i64> @rotl_select_commute(<2 x i64> %x, <2 x i64> %shamt) { 797; CHECK-LABEL: @rotl_select_commute( 798; CHECK-NEXT: [[R:%.*]] = call <2 x i64> @llvm.fshl.v2i64(<2 x i64> [[X:%.*]], <2 x i64> [[X]], <2 x i64> [[SHAMT:%.*]]) 799; CHECK-NEXT: ret <2 x i64> [[R]] 800; 801 %cmp = icmp eq <2 x i64> %shamt, zeroinitializer 802 %sub = sub <2 x i64> <i64 64, i64 64>, %shamt 803 %shr = lshr <2 x i64> %x, %sub 804 %shl = shl <2 x i64> %x, %shamt 805 %or = or <2 x i64> %shl, %shr 806 %r = select <2 x i1> %cmp, <2 x i64> %x, <2 x i64> %or 807 ret <2 x i64> %r 808} 809 810; Negative test - the transform is only valid with power-of-2 types. 811 812define i24 @rotl_select_weird_type(i24 %x, i24 %shamt) { 813; CHECK-LABEL: @rotl_select_weird_type( 814; CHECK-NEXT: [[CMP:%.*]] = icmp eq i24 [[SHAMT:%.*]], 0 815; CHECK-NEXT: [[SUB:%.*]] = sub i24 24, [[SHAMT]] 816; CHECK-NEXT: [[SHR:%.*]] = lshr i24 [[X:%.*]], [[SUB]] 817; CHECK-NEXT: [[SHL:%.*]] = shl i24 [[X]], [[SHAMT]] 818; CHECK-NEXT: [[OR:%.*]] = or i24 [[SHL]], [[SHR]] 819; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i24 [[X]], i24 [[OR]] 820; CHECK-NEXT: ret i24 [[R]] 821; 822 %cmp = icmp eq i24 %shamt, 0 823 %sub = sub i24 24, %shamt 824 %shr = lshr i24 %x, %sub 825 %shl = shl i24 %x, %shamt 826 %or = or i24 %shl, %shr 827 %r = select i1 %cmp, i24 %x, i24 %or 828 ret i24 %r 829} 830 831define i32 @rotl_select_zext_shamt(i32 %x, i8 %y) { 832; CHECK-LABEL: @rotl_select_zext_shamt( 833; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[Y:%.*]] to i32 834; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[TMP1]]) 835; CHECK-NEXT: ret i32 [[R]] 836; 837 %rem = and i8 %y, 31 838 %cmp = icmp eq i8 %rem, 0 839 %sh_prom = zext i8 %rem to i32 840 %sub = sub nuw nsw i8 32, %rem 841 %sh_prom1 = zext i8 %sub to i32 842 %shr = lshr i32 %x, %sh_prom1 843 %shl = shl i32 %x, %sh_prom 844 %or = or i32 %shl, %shr 845 %r = select i1 %cmp, i32 %x, i32 %or 846 ret i32 %r 847} 848 849define i64 @rotr_select_zext_shamt(i64 %x, i32 %y) { 850; CHECK-LABEL: @rotr_select_zext_shamt( 851; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[Y:%.*]] to i64 852; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 [[TMP1]]) 853; CHECK-NEXT: ret i64 [[R]] 854; 855 %rem = and i32 %y, 63 856 %cmp = icmp eq i32 %rem, 0 857 %sh_prom = zext i32 %rem to i64 858 %shr = lshr i64 %x, %sh_prom 859 %sub = sub nuw nsw i32 64, %rem 860 %sh_prom1 = zext i32 %sub to i64 861 %shl = shl i64 %x, %sh_prom1 862 %or = or i64 %shl, %shr 863 %r = select i1 %cmp, i64 %x, i64 %or 864 ret i64 %r 865} 866 867; Test that the transform doesn't crash when there's an "or" with a ConstantExpr operand. 868 869@external_global = external global i8 870 871define i32 @rotl_constant_expr(i32 %shamt) { 872; CHECK-LABEL: @rotl_constant_expr( 873; CHECK-NEXT: [[SHR:%.*]] = lshr i32 ptrtoint (i8* @external_global to i32), [[SHAMT:%.*]] 874; CHECK-NEXT: [[R:%.*]] = or i32 [[SHR]], shl (i32 ptrtoint (i8* @external_global to i32), i32 11) 875; CHECK-NEXT: ret i32 [[R]] 876; 877 %shr = lshr i32 ptrtoint (i8* @external_global to i32), %shamt 878 %r = or i32 %shr, shl (i32 ptrtoint (i8* @external_global to i32), i32 11) 879 ret i32 %r 880} 881 882; PR20750 - https://bugs.llvm.org/show_bug.cgi?id=20750 883; This IR corresponds to C source where the shift amount is a smaller type than the rotated value: 884; unsigned int rotate32_doubleand1(unsigned int v, unsigned char r) { r = r & 31; return (v << r) | (v >> (((32 - r)) & 31)); } 885 886define i32 @rotateleft32_doubleand1(i32 %v, i8 %r) { 887; CHECK-LABEL: @rotateleft32_doubleand1( 888; CHECK-NEXT: [[Z:%.*]] = zext i8 [[R:%.*]] to i32 889; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshl.i32(i32 [[V:%.*]], i32 [[V]], i32 [[Z]]) 890; CHECK-NEXT: ret i32 [[OR]] 891; 892 %m = and i8 %r, 31 893 %z = zext i8 %m to i32 894 %neg = sub nsw i32 0, %z 895 %and2 = and i32 %neg, 31 896 %shl = shl i32 %v, %z 897 %shr = lshr i32 %v, %and2 898 %or = or i32 %shr, %shl 899 ret i32 %or 900} 901 902define i32 @rotateright32_doubleand1(i32 %v, i16 %r) { 903; CHECK-LABEL: @rotateright32_doubleand1( 904; CHECK-NEXT: [[Z:%.*]] = zext i16 [[R:%.*]] to i32 905; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshr.i32(i32 [[V:%.*]], i32 [[V]], i32 [[Z]]) 906; CHECK-NEXT: ret i32 [[OR]] 907; 908 %m = and i16 %r, 31 909 %z = zext i16 %m to i32 910 %neg = sub nsw i32 0, %z 911 %and2 = and i32 %neg, 31 912 %shl = shl i32 %v, %and2 913 %shr = lshr i32 %v, %z 914 %or = or i32 %shr, %shl 915 ret i32 %or 916} 917