1089 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3; RUN: opt < %s -passes=instcombine -use-constant-int-for-fixed-length-splat -S | FileCheck %s4 5target 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"6 7; Canonicalize rotate by constant to funnel shift intrinsics.8; This should help cost modeling for vectorization, inlining, etc.9; If a target does not have a rotate instruction, the expansion will10; be exactly these same 3 basic ops (shl/lshr/or).11 12define i32 @rotl_i32_constant(i32 %x) {13; CHECK-LABEL: @rotl_i32_constant(14; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 11)15; CHECK-NEXT: ret i32 [[R]]16;17 %shl = shl i32 %x, 1118 %shr = lshr i32 %x, 2119 %r = or i32 %shr, %shl20 ret i32 %r21}22 23define i42 @rotr_i42_constant(i42 %x) {24; CHECK-LABEL: @rotr_i42_constant(25; CHECK-NEXT: [[R:%.*]] = call i42 @llvm.fshl.i42(i42 [[X:%.*]], i42 [[X]], i42 31)26; CHECK-NEXT: ret i42 [[R]]27;28 %shl = shl i42 %x, 3129 %shr = lshr i42 %x, 1130 %r = or i42 %shr, %shl31 ret i42 %r32}33 34define i8 @rotr_i8_constant_commute(i8 %x) {35; CHECK-LABEL: @rotr_i8_constant_commute(36; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 5)37; CHECK-NEXT: ret i8 [[R]]38;39 %shl = shl i8 %x, 540 %shr = lshr i8 %x, 341 %r = or i8 %shl, %shr42 ret i8 %r43}44 45define i88 @rotl_i88_constant_commute(i88 %x) {46; CHECK-LABEL: @rotl_i88_constant_commute(47; CHECK-NEXT: [[R:%.*]] = call i88 @llvm.fshl.i88(i88 [[X:%.*]], i88 [[X]], i88 44)48; CHECK-NEXT: ret i88 [[R]]49;50 %shl = shl i88 %x, 4451 %shr = lshr i88 %x, 4452 %r = or i88 %shl, %shr53 ret i88 %r54}55 56; Vector types are allowed.57 58define <2 x i16> @rotl_v2i16_constant_splat(<2 x i16> %x) {59; CHECK-LABEL: @rotl_v2i16_constant_splat(60; CHECK-NEXT: [[R:%.*]] = call <2 x i16> @llvm.fshl.v2i16(<2 x i16> [[X:%.*]], <2 x i16> [[X]], <2 x i16> splat (i16 1))61; CHECK-NEXT: ret <2 x i16> [[R]]62;63 %shl = shl <2 x i16> %x, <i16 1, i16 1>64 %shr = lshr <2 x i16> %x, <i16 15, i16 15>65 %r = or <2 x i16> %shl, %shr66 ret <2 x i16> %r67}68 69define <2 x i16> @rotl_v2i16_constant_splat_poison0(<2 x i16> %x) {70; CHECK-LABEL: @rotl_v2i16_constant_splat_poison0(71; CHECK-NEXT: [[R:%.*]] = call <2 x i16> @llvm.fshl.v2i16(<2 x i16> [[X:%.*]], <2 x i16> [[X]], <2 x i16> splat (i16 1))72; CHECK-NEXT: ret <2 x i16> [[R]]73;74 %shl = shl <2 x i16> %x, <i16 poison, i16 1>75 %shr = lshr <2 x i16> %x, <i16 15, i16 15>76 %r = or <2 x i16> %shl, %shr77 ret <2 x i16> %r78}79 80define <2 x i16> @rotl_v2i16_constant_splat_poison1(<2 x i16> %x) {81; CHECK-LABEL: @rotl_v2i16_constant_splat_poison1(82; CHECK-NEXT: [[R:%.*]] = call <2 x i16> @llvm.fshl.v2i16(<2 x i16> [[X:%.*]], <2 x i16> [[X]], <2 x i16> splat (i16 1))83; CHECK-NEXT: ret <2 x i16> [[R]]84;85 %shl = shl <2 x i16> %x, <i16 1, i16 1>86 %shr = lshr <2 x i16> %x, <i16 15, i16 poison>87 %r = or <2 x i16> %shl, %shr88 ret <2 x i16> %r89}90 91; Non-power-of-2 vector types are allowed.92 93define <2 x i17> @rotr_v2i17_constant_splat(<2 x i17> %x) {94; CHECK-LABEL: @rotr_v2i17_constant_splat(95; CHECK-NEXT: [[R:%.*]] = call <2 x i17> @llvm.fshl.v2i17(<2 x i17> [[X:%.*]], <2 x i17> [[X]], <2 x i17> splat (i17 12))96; CHECK-NEXT: ret <2 x i17> [[R]]97;98 %shl = shl <2 x i17> %x, <i17 12, i17 12>99 %shr = lshr <2 x i17> %x, <i17 5, i17 5>100 %r = or <2 x i17> %shr, %shl101 ret <2 x i17> %r102}103 104define <2 x i17> @rotr_v2i17_constant_splat_poison0(<2 x i17> %x) {105; CHECK-LABEL: @rotr_v2i17_constant_splat_poison0(106; CHECK-NEXT: [[R:%.*]] = call <2 x i17> @llvm.fshl.v2i17(<2 x i17> [[X:%.*]], <2 x i17> [[X]], <2 x i17> splat (i17 12))107; CHECK-NEXT: ret <2 x i17> [[R]]108;109 %shl = shl <2 x i17> %x, <i17 12, i17 poison>110 %shr = lshr <2 x i17> %x, <i17 poison, i17 5>111 %r = or <2 x i17> %shr, %shl112 ret <2 x i17> %r113}114 115define <2 x i17> @rotr_v2i17_constant_splat_poison1(<2 x i17> %x) {116; CHECK-LABEL: @rotr_v2i17_constant_splat_poison1(117; CHECK-NEXT: [[R:%.*]] = call <2 x i17> @llvm.fshl.v2i17(<2 x i17> [[X:%.*]], <2 x i17> [[X]], <2 x i17> splat (i17 12))118; CHECK-NEXT: ret <2 x i17> [[R]]119;120 %shl = shl <2 x i17> %x, <i17 12, i17 poison>121 %shr = lshr <2 x i17> %x, <i17 5, i17 poison>122 %r = or <2 x i17> %shr, %shl123 ret <2 x i17> %r124}125 126; Allow arbitrary shift constants.127; Support poison elements.128 129define <2 x i32> @rotr_v2i32_constant_nonsplat(<2 x i32> %x) {130; CHECK-LABEL: @rotr_v2i32_constant_nonsplat(131; 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>)132; CHECK-NEXT: ret <2 x i32> [[R]]133;134 %shl = shl <2 x i32> %x, <i32 17, i32 19>135 %shr = lshr <2 x i32> %x, <i32 15, i32 13>136 %r = or <2 x i32> %shl, %shr137 ret <2 x i32> %r138}139 140define <2 x i32> @rotr_v2i32_constant_nonsplat_poison0(<2 x i32> %x) {141; CHECK-LABEL: @rotr_v2i32_constant_nonsplat_poison0(142; CHECK-NEXT: [[R:%.*]] = call <2 x i32> @llvm.fshl.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[X]], <2 x i32> <i32 poison, i32 19>)143; CHECK-NEXT: ret <2 x i32> [[R]]144;145 %shl = shl <2 x i32> %x, <i32 poison, i32 19>146 %shr = lshr <2 x i32> %x, <i32 15, i32 13>147 %r = or <2 x i32> %shl, %shr148 ret <2 x i32> %r149}150 151define <2 x i32> @rotr_v2i32_constant_nonsplat_poison1(<2 x i32> %x) {152; CHECK-LABEL: @rotr_v2i32_constant_nonsplat_poison1(153; 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>)154; CHECK-NEXT: ret <2 x i32> [[R]]155;156 %shl = shl <2 x i32> %x, <i32 17, i32 19>157 %shr = lshr <2 x i32> %x, <i32 15, i32 poison>158 %r = or <2 x i32> %shl, %shr159 ret <2 x i32> %r160}161 162define <2 x i36> @rotl_v2i36_constant_nonsplat(<2 x i36> %x) {163; CHECK-LABEL: @rotl_v2i36_constant_nonsplat(164; 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>)165; CHECK-NEXT: ret <2 x i36> [[R]]166;167 %shl = shl <2 x i36> %x, <i36 21, i36 11>168 %shr = lshr <2 x i36> %x, <i36 15, i36 25>169 %r = or <2 x i36> %shl, %shr170 ret <2 x i36> %r171}172 173define <3 x i36> @rotl_v3i36_constant_nonsplat_poison0(<3 x i36> %x) {174; CHECK-LABEL: @rotl_v3i36_constant_nonsplat_poison0(175; 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 poison>)176; CHECK-NEXT: ret <3 x i36> [[R]]177;178 %shl = shl <3 x i36> %x, <i36 21, i36 11, i36 poison>179 %shr = lshr <3 x i36> %x, <i36 15, i36 25, i36 poison>180 %r = or <3 x i36> %shl, %shr181 ret <3 x i36> %r182}183 184; The most basic rotate by variable - no guards for UB due to oversized shifts.185; This cannot be canonicalized to funnel shift target-independently. The safe186; expansion includes masking for the shift amount that is not included here,187; so it could be more expensive.188 189define i32 @rotl_i32(i32 %x, i32 %y) {190; CHECK-LABEL: @rotl_i32(191; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[Y:%.*]]192; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], [[Y]]193; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X]], [[SUB]]194; CHECK-NEXT: [[R:%.*]] = or disjoint i32 [[SHR]], [[SHL]]195; CHECK-NEXT: ret i32 [[R]]196;197 %sub = sub i32 32, %y198 %shl = shl i32 %x, %y199 %shr = lshr i32 %x, %sub200 %r = or i32 %shr, %shl201 ret i32 %r202}203 204; Non-power-of-2 types should follow the same reasoning. Left/right is determined by subtract.205 206define i37 @rotr_i37(i37 %x, i37 %y) {207; CHECK-LABEL: @rotr_i37(208; CHECK-NEXT: [[SUB:%.*]] = sub i37 37, [[Y:%.*]]209; CHECK-NEXT: [[SHL:%.*]] = shl i37 [[X:%.*]], [[SUB]]210; CHECK-NEXT: [[SHR:%.*]] = lshr i37 [[X]], [[Y]]211; CHECK-NEXT: [[R:%.*]] = or disjoint i37 [[SHR]], [[SHL]]212; CHECK-NEXT: ret i37 [[R]]213;214 %sub = sub i37 37, %y215 %shl = shl i37 %x, %sub216 %shr = lshr i37 %x, %y217 %r = or i37 %shr, %shl218 ret i37 %r219}220 221; Commute 'or' operands.222 223define i8 @rotr_i8_commute(i8 %x, i8 %y) {224; CHECK-LABEL: @rotr_i8_commute(225; CHECK-NEXT: [[SUB:%.*]] = sub i8 8, [[Y:%.*]]226; CHECK-NEXT: [[SHL:%.*]] = shl i8 [[X:%.*]], [[SUB]]227; CHECK-NEXT: [[SHR:%.*]] = lshr i8 [[X]], [[Y]]228; CHECK-NEXT: [[R:%.*]] = or disjoint i8 [[SHL]], [[SHR]]229; CHECK-NEXT: ret i8 [[R]]230;231 %sub = sub i8 8, %y232 %shl = shl i8 %x, %sub233 %shr = lshr i8 %x, %y234 %r = or i8 %shl, %shr235 ret i8 %r236}237 238; Vector types should follow the same rules.239 240define <4 x i32> @rotl_v4i32(<4 x i32> %x, <4 x i32> %y) {241; CHECK-LABEL: @rotl_v4i32(242; CHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 32), [[Y:%.*]]243; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y]]244; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], [[SUB]]245; CHECK-NEXT: [[R:%.*]] = or disjoint <4 x i32> [[SHL]], [[SHR]]246; CHECK-NEXT: ret <4 x i32> [[R]]247;248 %sub = sub <4 x i32> <i32 32, i32 32, i32 32, i32 32>, %y249 %shl = shl <4 x i32> %x, %y250 %shr = lshr <4 x i32> %x, %sub251 %r = or <4 x i32> %shl, %shr252 ret <4 x i32> %r253}254 255; Non-power-of-2 vector types should follow the same rules.256 257define <3 x i42> @rotr_v3i42(<3 x i42> %x, <3 x i42> %y) {258; CHECK-LABEL: @rotr_v3i42(259; CHECK-NEXT: [[SUB:%.*]] = sub <3 x i42> splat (i42 42), [[Y:%.*]]260; CHECK-NEXT: [[SHL:%.*]] = shl <3 x i42> [[X:%.*]], [[SUB]]261; CHECK-NEXT: [[SHR:%.*]] = lshr <3 x i42> [[X]], [[Y]]262; CHECK-NEXT: [[R:%.*]] = or disjoint <3 x i42> [[SHR]], [[SHL]]263; CHECK-NEXT: ret <3 x i42> [[R]]264;265 %sub = sub <3 x i42> <i42 42, i42 42, i42 42>, %y266 %shl = shl <3 x i42> %x, %sub267 %shr = lshr <3 x i42> %x, %y268 %r = or <3 x i42> %shr, %shl269 ret <3 x i42> %r270}271 272; This is the canonical pattern for a UB-safe rotate-by-variable with power-of-2-size scalar type.273; The backend expansion of funnel shift for targets that don't have a rotate instruction should274; match the original IR, so it is always good to canonicalize to the intrinsics for this pattern.275 276define i32 @rotl_safe_i32(i32 %x, i32 %y) {277; CHECK-LABEL: @rotl_safe_i32(278; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]])279; CHECK-NEXT: ret i32 [[R]]280;281 %negy = sub i32 0, %y282 %ymask = and i32 %y, 31283 %negymask = and i32 %negy, 31284 %shl = shl i32 %x, %ymask285 %shr = lshr i32 %x, %negymask286 %r = or i32 %shr, %shl287 ret i32 %r288}289 290; Extra uses don't change anything.291 292define i16 @rotl_safe_i16_commute_extra_use(i16 %x, i16 %y, ptr %p) {293; CHECK-LABEL: @rotl_safe_i16_commute_extra_use(294; CHECK-NEXT: [[NEGY:%.*]] = sub i16 0, [[Y:%.*]]295; CHECK-NEXT: [[NEGYMASK:%.*]] = and i16 [[NEGY]], 15296; CHECK-NEXT: store i16 [[NEGYMASK]], ptr [[P:%.*]], align 2297; CHECK-NEXT: [[R:%.*]] = call i16 @llvm.fshl.i16(i16 [[X:%.*]], i16 [[X]], i16 [[Y]])298; CHECK-NEXT: ret i16 [[R]]299;300 %negy = sub i16 0, %y301 %ymask = and i16 %y, 15302 %negymask = and i16 %negy, 15303 store i16 %negymask, ptr %p304 %shl = shl i16 %x, %ymask305 %shr = lshr i16 %x, %negymask306 %r = or i16 %shl, %shr307 ret i16 %r308}309 310; Left/right is determined by the negation.311 312define i64 @rotr_safe_i64(i64 %x, i64 %y) {313; CHECK-LABEL: @rotr_safe_i64(314; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Y:%.*]])315; CHECK-NEXT: ret i64 [[R]]316;317 %negy = sub i64 0, %y318 %ymask = and i64 %y, 63319 %negymask = and i64 %negy, 63320 %shl = shl i64 %x, %negymask321 %shr = lshr i64 %x, %ymask322 %r = or i64 %shr, %shl323 ret i64 %r324}325 326; Extra uses don't change anything.327 328define i8 @rotr_safe_i8_commute_extra_use(i8 %x, i8 %y, ptr %p) {329; CHECK-LABEL: @rotr_safe_i8_commute_extra_use(330; CHECK-NEXT: [[NEGY:%.*]] = sub i8 0, [[Y:%.*]]331; CHECK-NEXT: [[YMASK:%.*]] = and i8 [[Y]], 7332; CHECK-NEXT: [[NEGYMASK:%.*]] = and i8 [[NEGY]], 7333; CHECK-NEXT: [[SHL:%.*]] = shl i8 [[X:%.*]], [[NEGYMASK]]334; CHECK-NEXT: [[SHR:%.*]] = lshr i8 [[X]], [[YMASK]]335; CHECK-NEXT: store i8 [[SHR]], ptr [[P:%.*]], align 1336; CHECK-NEXT: [[R:%.*]] = or i8 [[SHL]], [[SHR]]337; CHECK-NEXT: ret i8 [[R]]338;339 %negy = sub i8 0, %y340 %ymask = and i8 %y, 7341 %negymask = and i8 %negy, 7342 %shl = shl i8 %x, %negymask343 %shr = lshr i8 %x, %ymask344 store i8 %shr, ptr %p345 %r = or i8 %shl, %shr346 ret i8 %r347}348 349; Vectors follow the same rules.350 351define <2 x i32> @rotl_safe_v2i32(<2 x i32> %x, <2 x i32> %y) {352; CHECK-LABEL: @rotl_safe_v2i32(353; CHECK-NEXT: [[R:%.*]] = call <2 x i32> @llvm.fshl.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[X]], <2 x i32> [[Y:%.*]])354; CHECK-NEXT: ret <2 x i32> [[R]]355;356 %negy = sub <2 x i32> zeroinitializer, %y357 %ymask = and <2 x i32> %y, <i32 31, i32 31>358 %negymask = and <2 x i32> %negy, <i32 31, i32 31>359 %shl = shl <2 x i32> %x, %ymask360 %shr = lshr <2 x i32> %x, %negymask361 %r = or <2 x i32> %shr, %shl362 ret <2 x i32> %r363}364 365; Vectors follow the same rules.366 367define <3 x i16> @rotr_safe_v3i16(<3 x i16> %x, <3 x i16> %y) {368; CHECK-LABEL: @rotr_safe_v3i16(369; CHECK-NEXT: [[R:%.*]] = call <3 x i16> @llvm.fshr.v3i16(<3 x i16> [[X:%.*]], <3 x i16> [[X]], <3 x i16> [[Y:%.*]])370; CHECK-NEXT: ret <3 x i16> [[R]]371;372 %negy = sub <3 x i16> zeroinitializer, %y373 %ymask = and <3 x i16> %y, <i16 15, i16 15, i16 15>374 %negymask = and <3 x i16> %negy, <i16 15, i16 15, i16 15>375 %shl = shl <3 x i16> %x, %negymask376 %shr = lshr <3 x i16> %x, %ymask377 %r = or <3 x i16> %shr, %shl378 ret <3 x i16> %r379}380 381; These are optionally UB-free rotate left/right patterns that are narrowed to a smaller bitwidth.382; See PR34046, PR16726, and PR39624 for motivating examples:383; https://bugs.llvm.org/show_bug.cgi?id=34046384; https://bugs.llvm.org/show_bug.cgi?id=16726385; https://bugs.llvm.org/show_bug.cgi?id=39624386 387define i16 @rotate_left_16bit(i16 %v, i32 %shift) {388; CHECK-LABEL: @rotate_left_16bit(389; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHIFT:%.*]] to i16390; CHECK-NEXT: [[CONV2:%.*]] = call i16 @llvm.fshl.i16(i16 [[V:%.*]], i16 [[V]], i16 [[TMP1]])391; CHECK-NEXT: ret i16 [[CONV2]]392;393 %and = and i32 %shift, 15394 %conv = zext i16 %v to i32395 %shl = shl i32 %conv, %and396 %sub = sub i32 16, %and397 %shr = lshr i32 %conv, %sub398 %or = or i32 %shr, %shl399 %conv2 = trunc i32 %or to i16400 ret i16 %conv2401}402 403; Commute the 'or' operands and try a vector type.404 405define <2 x i16> @rotate_left_commute_16bit_vec(<2 x i16> %v, <2 x i32> %shift) {406; CHECK-LABEL: @rotate_left_commute_16bit_vec(407; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i32> [[SHIFT:%.*]] to <2 x i16>408; CHECK-NEXT: [[CONV2:%.*]] = call <2 x i16> @llvm.fshl.v2i16(<2 x i16> [[V:%.*]], <2 x i16> [[V]], <2 x i16> [[TMP1]])409; CHECK-NEXT: ret <2 x i16> [[CONV2]]410;411 %and = and <2 x i32> %shift, <i32 15, i32 15>412 %conv = zext <2 x i16> %v to <2 x i32>413 %shl = shl <2 x i32> %conv, %and414 %sub = sub <2 x i32> <i32 16, i32 16>, %and415 %shr = lshr <2 x i32> %conv, %sub416 %or = or <2 x i32> %shl, %shr417 %conv2 = trunc <2 x i32> %or to <2 x i16>418 ret <2 x i16> %conv2419}420 421; Change the size, rotation direction (the subtract is on the left-shift), and mask op.422 423define i8 @rotate_right_8bit(i8 %v, i3 %shift) {424; CHECK-LABEL: @rotate_right_8bit(425; CHECK-NEXT: [[TMP1:%.*]] = zext i3 [[SHIFT:%.*]] to i8426; CHECK-NEXT: [[CONV2:%.*]] = call i8 @llvm.fshr.i8(i8 [[V:%.*]], i8 [[V]], i8 [[TMP1]])427; CHECK-NEXT: ret i8 [[CONV2]]428;429 %and = zext i3 %shift to i32430 %conv = zext i8 %v to i32431 %shr = lshr i32 %conv, %and432 %sub = sub i32 8, %and433 %shl = shl i32 %conv, %sub434 %or = or i32 %shl, %shr435 %conv2 = trunc i32 %or to i8436 ret i8 %conv2437}438 439; The right-shifted value does not need to be a zexted value; here it is masked.440; The shift mask could be less than the bitwidth, but this is still ok.441 442define i8 @rotate_right_commute_8bit_unmasked_shl(i32 %v, i32 %shift) {443; CHECK-LABEL: @rotate_right_commute_8bit_unmasked_shl(444; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHIFT:%.*]] to i8445; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], 3446; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[V:%.*]] to i8447; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[V]] to i8448; CHECK-NEXT: [[CONV2:%.*]] = call i8 @llvm.fshr.i8(i8 [[TMP3]], i8 [[TMP4]], i8 [[TMP2]])449; CHECK-NEXT: ret i8 [[CONV2]]450;451 %and = and i32 %shift, 3452 %conv = and i32 %v, 255453 %shr = lshr i32 %conv, %and454 %sub = sub i32 8, %and455 %shl = shl i32 %conv, %sub456 %or = or i32 %shr, %shl457 %conv2 = trunc i32 %or to i8458 ret i8 %conv2459}460 461; The left-shifted value does not need to be masked at all.462 463define i8 @rotate_right_commute_8bit(i32 %v, i32 %shift) {464; CHECK-LABEL: @rotate_right_commute_8bit(465; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHIFT:%.*]] to i8466; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], 3467; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[V:%.*]] to i8468; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[V]] to i8469; CHECK-NEXT: [[CONV2:%.*]] = call i8 @llvm.fshr.i8(i8 [[TMP3]], i8 [[TMP4]], i8 [[TMP2]])470; CHECK-NEXT: ret i8 [[CONV2]]471;472 %and = and i32 %shift, 3473 %conv = and i32 %v, 255474 %shr = lshr i32 %conv, %and475 %sub = sub i32 8, %and476 %shl = shl i32 %v, %sub477 %or = or i32 %shr, %shl478 %conv2 = trunc i32 %or to i8479 ret i8 %conv2480}481 482; If the original source does not mask the shift amount,483; we still do the transform by adding masks to make it safe.484 485define i8 @rotate8_not_safe(i8 %v, i32 %shamt) {486; CHECK-LABEL: @rotate8_not_safe(487; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHAMT:%.*]] to i8488; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.fshl.i8(i8 [[V:%.*]], i8 [[V]], i8 [[TMP1]])489; CHECK-NEXT: ret i8 [[RET]]490;491 %conv = zext i8 %v to i32492 %sub = sub i32 8, %shamt493 %shr = lshr i32 %conv, %sub494 %shl = shl i32 %conv, %shamt495 %or = or i32 %shr, %shl496 %ret = trunc i32 %or to i8497 ret i8 %ret498}499 500; A non-power-of-2 destination type can't be masked as above.501 502define i9 @rotate9_not_safe(i9 %v, i32 %shamt) {503; CHECK-LABEL: @rotate9_not_safe(504; CHECK-NEXT: [[CONV:%.*]] = zext i9 [[V:%.*]] to i32505; CHECK-NEXT: [[SUB:%.*]] = sub i32 9, [[SHAMT:%.*]]506; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[CONV]], [[SUB]]507; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[CONV]], [[SHAMT]]508; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHR]], [[SHL]]509; CHECK-NEXT: [[RET:%.*]] = trunc i32 [[OR]] to i9510; CHECK-NEXT: ret i9 [[RET]]511;512 %conv = zext i9 %v to i32513 %sub = sub i32 9, %shamt514 %shr = lshr i32 %conv, %sub515 %shl = shl i32 %conv, %shamt516 %or = or i32 %shr, %shl517 %ret = trunc i32 %or to i9518 ret i9 %ret519}520 521; We should narrow (v << (s & 15)) | (v >> (-s & 15))522; when both v and s have been promoted.523 524define i16 @rotateleft_16_neg_mask(i16 %v, i16 %shamt) {525; CHECK-LABEL: @rotateleft_16_neg_mask(526; CHECK-NEXT: [[OR:%.*]] = call i16 @llvm.fshl.i16(i16 [[V:%.*]], i16 [[V]], i16 [[SHAMT:%.*]])527; CHECK-NEXT: ret i16 [[OR]]528;529 %neg = sub i16 0, %shamt530 %lshamt = and i16 %shamt, 15531 %lshamtconv = zext i16 %lshamt to i32532 %rshamt = and i16 %neg, 15533 %rshamtconv = zext i16 %rshamt to i32534 %conv = zext i16 %v to i32535 %shl = shl i32 %conv, %lshamtconv536 %shr = lshr i32 %conv, %rshamtconv537 %or = or i32 %shr, %shl538 %ret = trunc i32 %or to i16539 ret i16 %ret540}541 542define i16 @rotateleft_16_neg_mask_commute(i16 %v, i16 %shamt) {543; CHECK-LABEL: @rotateleft_16_neg_mask_commute(544; CHECK-NEXT: [[OR:%.*]] = call i16 @llvm.fshl.i16(i16 [[V:%.*]], i16 [[V]], i16 [[SHAMT:%.*]])545; CHECK-NEXT: ret i16 [[OR]]546;547 %neg = sub i16 0, %shamt548 %lshamt = and i16 %shamt, 15549 %lshamtconv = zext i16 %lshamt to i32550 %rshamt = and i16 %neg, 15551 %rshamtconv = zext i16 %rshamt to i32552 %conv = zext i16 %v to i32553 %shl = shl i32 %conv, %lshamtconv554 %shr = lshr i32 %conv, %rshamtconv555 %or = or i32 %shl, %shr556 %ret = trunc i32 %or to i16557 ret i16 %ret558}559 560define i8 @rotateright_8_neg_mask(i8 %v, i8 %shamt) {561; CHECK-LABEL: @rotateright_8_neg_mask(562; CHECK-NEXT: [[OR:%.*]] = call i8 @llvm.fshr.i8(i8 [[V:%.*]], i8 [[V]], i8 [[SHAMT:%.*]])563; CHECK-NEXT: ret i8 [[OR]]564;565 %neg = sub i8 0, %shamt566 %rshamt = and i8 %shamt, 7567 %rshamtconv = zext i8 %rshamt to i32568 %lshamt = and i8 %neg, 7569 %lshamtconv = zext i8 %lshamt to i32570 %conv = zext i8 %v to i32571 %shl = shl i32 %conv, %lshamtconv572 %shr = lshr i32 %conv, %rshamtconv573 %or = or i32 %shr, %shl574 %ret = trunc i32 %or to i8575 ret i8 %ret576}577 578define i8 @rotateright_8_neg_mask_commute(i8 %v, i8 %shamt) {579; CHECK-LABEL: @rotateright_8_neg_mask_commute(580; CHECK-NEXT: [[OR:%.*]] = call i8 @llvm.fshr.i8(i8 [[V:%.*]], i8 [[V]], i8 [[SHAMT:%.*]])581; CHECK-NEXT: ret i8 [[OR]]582;583 %neg = sub i8 0, %shamt584 %rshamt = and i8 %shamt, 7585 %rshamtconv = zext i8 %rshamt to i32586 %lshamt = and i8 %neg, 7587 %lshamtconv = zext i8 %lshamt to i32588 %conv = zext i8 %v to i32589 %shl = shl i32 %conv, %lshamtconv590 %shr = lshr i32 %conv, %rshamtconv591 %or = or i32 %shl, %shr592 %ret = trunc i32 %or to i8593 ret i8 %ret594}595 596; The shift amount may already be in the wide type,597; so we need to truncate it going into the rotate pattern.598 599define i16 @rotateright_16_neg_mask_wide_amount(i16 %v, i32 %shamt) {600; CHECK-LABEL: @rotateright_16_neg_mask_wide_amount(601; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHAMT:%.*]] to i16602; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.fshr.i16(i16 [[V:%.*]], i16 [[V]], i16 [[TMP1]])603; CHECK-NEXT: ret i16 [[RET]]604;605 %neg = sub i32 0, %shamt606 %rshamt = and i32 %shamt, 15607 %lshamt = and i32 %neg, 15608 %conv = zext i16 %v to i32609 %shl = shl i32 %conv, %lshamt610 %shr = lshr i32 %conv, %rshamt611 %or = or i32 %shr, %shl612 %ret = trunc i32 %or to i16613 ret i16 %ret614}615 616define i16 @rotateright_16_neg_mask_wide_amount_commute(i16 %v, i32 %shamt) {617; CHECK-LABEL: @rotateright_16_neg_mask_wide_amount_commute(618; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHAMT:%.*]] to i16619; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.fshr.i16(i16 [[V:%.*]], i16 [[V]], i16 [[TMP1]])620; CHECK-NEXT: ret i16 [[RET]]621;622 %neg = sub i32 0, %shamt623 %rshamt = and i32 %shamt, 15624 %lshamt = and i32 %neg, 15625 %conv = zext i16 %v to i32626 %shl = shl i32 %conv, %lshamt627 %shr = lshr i32 %conv, %rshamt628 %or = or i32 %shl, %shr629 %ret = trunc i32 %or to i16630 ret i16 %ret631}632 633define i64 @rotateright_64_zext_neg_mask_amount(i64 %0, i32 %1) {634; CHECK-LABEL: @rotateright_64_zext_neg_mask_amount(635; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[TMP1:%.*]] to i64636; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP0:%.*]], i64 [[TMP0]], i64 [[TMP3]])637; CHECK-NEXT: ret i64 [[TMP4]]638;639 %3 = and i32 %1, 63640 %4 = zext i32 %3 to i64641 %5 = lshr i64 %0, %4642 %6 = sub nsw i32 0, %1643 %7 = and i32 %6, 63644 %8 = zext i32 %7 to i64645 %9 = shl i64 %0, %8646 %10 = or i64 %5, %9647 ret i64 %10648}649 650define i8 @rotateleft_8_neg_mask_wide_amount(i8 %v, i32 %shamt) {651; CHECK-LABEL: @rotateleft_8_neg_mask_wide_amount(652; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHAMT:%.*]] to i8653; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.fshl.i8(i8 [[V:%.*]], i8 [[V]], i8 [[TMP1]])654; CHECK-NEXT: ret i8 [[RET]]655;656 %neg = sub i32 0, %shamt657 %lshamt = and i32 %shamt, 7658 %rshamt = and i32 %neg, 7659 %conv = zext i8 %v to i32660 %shl = shl i32 %conv, %lshamt661 %shr = lshr i32 %conv, %rshamt662 %or = or i32 %shr, %shl663 %ret = trunc i32 %or to i8664 ret i8 %ret665}666 667define i8 @rotateleft_8_neg_mask_wide_amount_commute(i8 %v, i32 %shamt) {668; CHECK-LABEL: @rotateleft_8_neg_mask_wide_amount_commute(669; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHAMT:%.*]] to i8670; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.fshl.i8(i8 [[V:%.*]], i8 [[V]], i8 [[TMP1]])671; CHECK-NEXT: ret i8 [[RET]]672;673 %neg = sub i32 0, %shamt674 %lshamt = and i32 %shamt, 7675 %rshamt = and i32 %neg, 7676 %conv = zext i8 %v to i32677 %shl = shl i32 %conv, %lshamt678 %shr = lshr i32 %conv, %rshamt679 %or = or i32 %shl, %shr680 %ret = trunc i32 %or to i8681 ret i8 %ret682}683 684define i64 @rotateleft_64_zext_neg_mask_amount(i64 %0, i32 %1) {685; CHECK-LABEL: @rotateleft_64_zext_neg_mask_amount(686; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[TMP1:%.*]] to i64687; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.fshl.i64(i64 [[TMP0:%.*]], i64 [[TMP0]], i64 [[TMP3]])688; CHECK-NEXT: ret i64 [[TMP4]]689;690 %3 = and i32 %1, 63691 %4 = zext i32 %3 to i64692 %5 = shl i64 %0, %4693 %6 = sub nsw i32 0, %1694 %7 = and i32 %6, 63695 %8 = zext i32 %7 to i64696 %9 = lshr i64 %0, %8697 %10 = or i64 %5, %9698 ret i64 %10699}700 701; Non-power-of-2 types. This could be transformed, but it's not a typical rotate pattern.702 703define i9 @rotateleft_9_neg_mask_wide_amount_commute(i9 %v, i33 %shamt) {704; CHECK-LABEL: @rotateleft_9_neg_mask_wide_amount_commute(705; CHECK-NEXT: [[NEG:%.*]] = sub i33 0, [[SHAMT:%.*]]706; CHECK-NEXT: [[LSHAMT:%.*]] = and i33 [[SHAMT]], 8707; CHECK-NEXT: [[RSHAMT:%.*]] = and i33 [[NEG]], 8708; CHECK-NEXT: [[CONV:%.*]] = zext i9 [[V:%.*]] to i33709; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i33 [[CONV]], [[LSHAMT]]710; CHECK-NEXT: [[SHR:%.*]] = lshr i33 [[CONV]], [[RSHAMT]]711; CHECK-NEXT: [[OR:%.*]] = or i33 [[SHL]], [[SHR]]712; CHECK-NEXT: [[RET:%.*]] = trunc i33 [[OR]] to i9713; CHECK-NEXT: ret i9 [[RET]]714;715 %neg = sub i33 0, %shamt716 %lshamt = and i33 %shamt, 8717 %rshamt = and i33 %neg, 8718 %conv = zext i9 %v to i33719 %shl = shl i33 %conv, %lshamt720 %shr = lshr i33 %conv, %rshamt721 %or = or i33 %shl, %shr722 %ret = trunc i33 %or to i9723 ret i9 %ret724}725 726; Fold or(shl(v,x),lshr(v,bw-x)) iff x < bw727 728define i64 @rotl_sub_mask(i64 %0, i64 %1) {729; CHECK-LABEL: @rotl_sub_mask(730; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.fshl.i64(i64 [[TMP0:%.*]], i64 [[TMP0]], i64 [[TMP1:%.*]])731; CHECK-NEXT: ret i64 [[TMP3]]732;733 %3 = and i64 %1, 63734 %4 = shl i64 %0, %3735 %5 = sub nuw nsw i64 64, %3736 %6 = lshr i64 %0, %5737 %7 = or i64 %6, %4738 ret i64 %7739}740 741; Fold or(lshr(v,x),shl(v,bw-x)) iff x < bw742 743define i64 @rotr_sub_mask(i64 %0, i64 %1) {744; CHECK-LABEL: @rotr_sub_mask(745; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP0:%.*]], i64 [[TMP0]], i64 [[TMP1:%.*]])746; CHECK-NEXT: ret i64 [[TMP3]]747;748 %3 = and i64 %1, 63749 %4 = lshr i64 %0, %3750 %5 = sub nuw nsw i64 64, %3751 %6 = shl i64 %0, %5752 %7 = or i64 %6, %4753 ret i64 %7754}755 756define <2 x i64> @rotr_sub_mask_vector(<2 x i64> %0, <2 x i64> %1) {757; CHECK-LABEL: @rotr_sub_mask_vector(758; CHECK-NEXT: [[TMP3:%.*]] = call <2 x i64> @llvm.fshr.v2i64(<2 x i64> [[TMP0:%.*]], <2 x i64> [[TMP0]], <2 x i64> [[TMP1:%.*]])759; CHECK-NEXT: ret <2 x i64> [[TMP3]]760;761 %3 = and <2 x i64> %1, <i64 63, i64 63>762 %4 = lshr <2 x i64> %0, %3763 %5 = sub nuw nsw <2 x i64> <i64 64, i64 64>, %3764 %6 = shl <2 x i64> %0, %5765 %7 = or <2 x i64> %6, %4766 ret <2 x i64> %7767}768 769; Convert select pattern to masked shift that ends in 'or'.770 771define i32 @rotr_select(i32 %x, i32 %shamt) {772; CHECK-LABEL: @rotr_select(773; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[SHAMT:%.*]])774; CHECK-NEXT: ret i32 [[R]]775;776 %cmp = icmp eq i32 %shamt, 0777 %sub = sub i32 32, %shamt778 %shr = lshr i32 %x, %shamt779 %shl = shl i32 %x, %sub780 %or = or i32 %shr, %shl781 %r = select i1 %cmp, i32 %x, i32 %or782 ret i32 %r783}784 785; Convert select pattern to masked shift that ends in 'or'.786 787define i8 @rotr_select_commute(i8 %x, i8 %shamt) {788; CHECK-LABEL: @rotr_select_commute(789; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[SHAMT:%.*]])790; CHECK-NEXT: ret i8 [[R]]791;792 %cmp = icmp eq i8 %shamt, 0793 %sub = sub i8 8, %shamt794 %shr = lshr i8 %x, %shamt795 %shl = shl i8 %x, %sub796 %or = or i8 %shl, %shr797 %r = select i1 %cmp, i8 %x, i8 %or798 ret i8 %r799}800 801; Convert select pattern to masked shift that ends in 'or'.802 803define i16 @rotl_select(i16 %x, i16 %shamt) {804; CHECK-LABEL: @rotl_select(805; CHECK-NEXT: [[R:%.*]] = call i16 @llvm.fshl.i16(i16 [[X:%.*]], i16 [[X]], i16 [[SHAMT:%.*]])806; CHECK-NEXT: ret i16 [[R]]807;808 %cmp = icmp eq i16 %shamt, 0809 %sub = sub i16 16, %shamt810 %shr = lshr i16 %x, %sub811 %shl = shl i16 %x, %shamt812 %or = or i16 %shr, %shl813 %r = select i1 %cmp, i16 %x, i16 %or814 ret i16 %r815}816 817; Convert select pattern to masked shift that ends in 'or'.818 819define <2 x i64> @rotl_select_commute(<2 x i64> %x, <2 x i64> %shamt) {820; CHECK-LABEL: @rotl_select_commute(821; CHECK-NEXT: [[R:%.*]] = call <2 x i64> @llvm.fshl.v2i64(<2 x i64> [[X:%.*]], <2 x i64> [[X]], <2 x i64> [[SHAMT:%.*]])822; CHECK-NEXT: ret <2 x i64> [[R]]823;824 %cmp = icmp eq <2 x i64> %shamt, zeroinitializer825 %sub = sub <2 x i64> <i64 64, i64 64>, %shamt826 %shr = lshr <2 x i64> %x, %sub827 %shl = shl <2 x i64> %x, %shamt828 %or = or <2 x i64> %shl, %shr829 %r = select <2 x i1> %cmp, <2 x i64> %x, <2 x i64> %or830 ret <2 x i64> %r831}832 833; Negative test - the transform is only valid with power-of-2 types.834 835define i24 @rotl_select_weird_type(i24 %x, i24 %shamt) {836; CHECK-LABEL: @rotl_select_weird_type(837; CHECK-NEXT: [[CMP:%.*]] = icmp eq i24 [[SHAMT:%.*]], 0838; CHECK-NEXT: [[SUB:%.*]] = sub i24 24, [[SHAMT]]839; CHECK-NEXT: [[SHR:%.*]] = lshr i24 [[X:%.*]], [[SUB]]840; CHECK-NEXT: [[SHL:%.*]] = shl i24 [[X]], [[SHAMT]]841; CHECK-NEXT: [[OR:%.*]] = or disjoint i24 [[SHL]], [[SHR]]842; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i24 [[X]], i24 [[OR]]843; CHECK-NEXT: ret i24 [[R]]844;845 %cmp = icmp eq i24 %shamt, 0846 %sub = sub i24 24, %shamt847 %shr = lshr i24 %x, %sub848 %shl = shl i24 %x, %shamt849 %or = or i24 %shl, %shr850 %r = select i1 %cmp, i24 %x, i24 %or851 ret i24 %r852}853 854define i32 @rotl_select_zext_shamt(i32 %x, i8 %y) {855; CHECK-LABEL: @rotl_select_zext_shamt(856; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[Y:%.*]] to i32857; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[TMP1]])858; CHECK-NEXT: ret i32 [[R]]859;860 %rem = and i8 %y, 31861 %cmp = icmp eq i8 %rem, 0862 %sh_prom = zext i8 %rem to i32863 %sub = sub nuw nsw i8 32, %rem864 %sh_prom1 = zext i8 %sub to i32865 %shr = lshr i32 %x, %sh_prom1866 %shl = shl i32 %x, %sh_prom867 %or = or i32 %shl, %shr868 %r = select i1 %cmp, i32 %x, i32 %or869 ret i32 %r870}871 872define i64 @rotr_select_zext_shamt(i64 %x, i32 %y) {873; CHECK-LABEL: @rotr_select_zext_shamt(874; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[Y:%.*]] to i64875; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 [[TMP1]])876; CHECK-NEXT: ret i64 [[R]]877;878 %rem = and i32 %y, 63879 %cmp = icmp eq i32 %rem, 0880 %sh_prom = zext i32 %rem to i64881 %shr = lshr i64 %x, %sh_prom882 %sub = sub nuw nsw i32 64, %rem883 %sh_prom1 = zext i32 %sub to i64884 %shl = shl i64 %x, %sh_prom1885 %or = or i64 %shl, %shr886 %r = select i1 %cmp, i64 %x, i64 %or887 ret i64 %r888}889 890; Test that the transform doesn't crash when there's an "or" with a ConstantExpr operand.891 892@external_global = external global i8893 894define i32 @rotl_constant_expr(i32 %shamt) {895; CHECK-LABEL: @rotl_constant_expr(896; CHECK-NEXT: [[SHR:%.*]] = lshr i32 ptrtoint (ptr @external_global to i32), [[SHAMT:%.*]]897; CHECK-NEXT: [[SHL:%.*]] = shl i32 ptrtoint (ptr @external_global to i32), 11898; CHECK-NEXT: [[R:%.*]] = or i32 [[SHR]], [[SHL]]899; CHECK-NEXT: ret i32 [[R]]900;901 %shr = lshr i32 ptrtoint (ptr @external_global to i32), %shamt902 %shl = shl i32 ptrtoint (ptr @external_global to i32), 11903 %r = or i32 %shr, %shl904 ret i32 %r905}906 907; PR20750 - https://bugs.llvm.org/show_bug.cgi?id=20750908; This IR corresponds to C source where the shift amount is a smaller type than the rotated value:909; unsigned int rotate32_doubleand1(unsigned int v, unsigned char r) { r = r & 31; return (v << r) | (v >> (((32 - r)) & 31)); }910 911define i32 @rotateleft32_doubleand1(i32 %v, i8 %r) {912; CHECK-LABEL: @rotateleft32_doubleand1(913; CHECK-NEXT: [[Z:%.*]] = zext i8 [[R:%.*]] to i32914; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshl.i32(i32 [[V:%.*]], i32 [[V]], i32 [[Z]])915; CHECK-NEXT: ret i32 [[OR]]916;917 %m = and i8 %r, 31918 %z = zext i8 %m to i32919 %neg = sub nsw i32 0, %z920 %and2 = and i32 %neg, 31921 %shl = shl i32 %v, %z922 %shr = lshr i32 %v, %and2923 %or = or i32 %shr, %shl924 ret i32 %or925}926 927define i32 @rotateright32_doubleand1(i32 %v, i16 %r) {928; CHECK-LABEL: @rotateright32_doubleand1(929; CHECK-NEXT: [[Z:%.*]] = zext i16 [[R:%.*]] to i32930; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshr.i32(i32 [[V:%.*]], i32 [[V]], i32 [[Z]])931; CHECK-NEXT: ret i32 [[OR]]932;933 %m = and i16 %r, 31934 %z = zext i16 %m to i32935 %neg = sub nsw i32 0, %z936 %and2 = and i32 %neg, 31937 %shl = shl i32 %v, %and2938 %shr = lshr i32 %v, %z939 %or = or i32 %shr, %shl940 ret i32 %or941}942 943; TODO: This should be a rotate (funnel-shift).944 945define i8 @unmasked_shlop_unmasked_shift_amount(i32 %x, i32 %shamt) {946; CHECK-LABEL: @unmasked_shlop_unmasked_shift_amount(947; CHECK-NEXT: [[MASKX:%.*]] = and i32 [[X:%.*]], 255948; CHECK-NEXT: [[T4:%.*]] = sub i32 8, [[SHAMT:%.*]]949; CHECK-NEXT: [[T5:%.*]] = shl i32 [[X]], [[T4]]950; CHECK-NEXT: [[T6:%.*]] = lshr i32 [[MASKX]], [[SHAMT]]951; CHECK-NEXT: [[T7:%.*]] = or i32 [[T5]], [[T6]]952; CHECK-NEXT: [[T8:%.*]] = trunc i32 [[T7]] to i8953; CHECK-NEXT: ret i8 [[T8]]954;955 %maskx = and i32 %x, 255956 %t4 = sub i32 8, %shamt957 %t5 = shl i32 %x, %t4958 %t6 = lshr i32 %maskx, %shamt959 %t7 = or i32 %t5, %t6960 %t8 = trunc i32 %t7 to i8961 ret i8 %t8962}963 964define i16 @check_rotate_masked_16bit(i8 %shamt, i32 %cond) {965; CHECK-LABEL: @check_rotate_masked_16bit(966; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[SHAMT:%.*]] to i16967; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[COND:%.*]] to i16968; CHECK-NEXT: [[TMP3:%.*]] = and i16 [[TMP2]], 1969; CHECK-NEXT: [[TRUNC:%.*]] = call i16 @llvm.fshr.i16(i16 [[TMP3]], i16 [[TMP3]], i16 [[TMP1]])970; CHECK-NEXT: ret i16 [[TRUNC]]971;972 %maskx = and i32 %cond, 1973 %masky = and i8 %shamt, 15974 %z = zext i8 %masky to i32975 %shr = lshr i32 %maskx, %z976 %sub = sub i8 0, %shamt977 %maskw = and i8 %sub, 15978 %z2 = zext i8 %maskw to i32979 %shl = shl nuw nsw i32 %maskx, %z2980 %or = or i32 %shr, %shl981 %trunc = trunc i32 %or to i16982 ret i16 %trunc983}984 985define i32 @rotl_i32_add(i32 %x, i32 %y) {986; CHECK-LABEL: @rotl_i32_add(987; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[Y:%.*]]988; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], [[Y]]989; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X]], [[SUB]]990; CHECK-NEXT: [[R:%.*]] = or disjoint i32 [[SHR]], [[SHL]]991; CHECK-NEXT: ret i32 [[R]]992;993 %sub = sub i32 32, %y994 %shl = shl i32 %x, %y995 %shr = lshr i32 %x, %sub996 %r = add i32 %shr, %shl997 ret i32 %r998}999 1000define i32 @rotr_i32_add(i32 %x, i32 %y) {1001; CHECK-LABEL: @rotr_i32_add(1002; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[Y:%.*]]1003; CHECK-NEXT: [[SHL:%.*]] = lshr i32 [[X:%.*]], [[Y]]1004; CHECK-NEXT: [[SHR:%.*]] = shl i32 [[X]], [[SUB]]1005; CHECK-NEXT: [[R:%.*]] = or disjoint i32 [[SHR]], [[SHL]]1006; CHECK-NEXT: ret i32 [[R]]1007;1008 %sub = sub i32 32, %y1009 %shl = lshr i32 %x, %y1010 %shr = shl i32 %x, %sub1011 %r = add i32 %shr, %shl1012 ret i32 %r1013}1014 1015define i32 @fshr_i32_add(i32 %x, i32 %y, i32 %z) {1016; CHECK-LABEL: @fshr_i32_add(1017; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[Z:%.*]]1018; CHECK-NEXT: [[SHL:%.*]] = lshr i32 [[X:%.*]], [[Z]]1019; CHECK-NEXT: [[SHR:%.*]] = shl i32 [[Y:%.*]], [[SUB]]1020; CHECK-NEXT: [[R:%.*]] = or disjoint i32 [[SHR]], [[SHL]]1021; CHECK-NEXT: ret i32 [[R]]1022;1023 %sub = sub i32 32, %z1024 %shl = lshr i32 %x, %z1025 %shr = shl i32 %y, %sub1026 %r = add i32 %shr, %shl1027 ret i32 %r1028}1029 1030define i32 @fshl_i32_add(i32 %x, i32 %y, i32 %z) {1031; CHECK-LABEL: @fshl_i32_add(1032; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[Z:%.*]]1033; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[Y:%.*]], [[Z]]1034; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], [[SUB]]1035; CHECK-NEXT: [[R:%.*]] = or disjoint i32 [[SHR]], [[SHL]]1036; CHECK-NEXT: ret i32 [[R]]1037;1038 %sub = sub i32 32, %z1039 %shl = shl i32 %y, %z1040 %shr = lshr i32 %x, %sub1041 %r = add i32 %shr, %shl1042 ret i32 %r1043}1044 1045define i32 @rotl_i32_add_greater(i32 %x, i32 %y) {1046; CHECK-LABEL: @rotl_i32_add_greater(1047; CHECK-NEXT: [[SUB:%.*]] = sub i32 33, [[Y:%.*]]1048; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], [[Y]]1049; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X]], [[SUB]]1050; CHECK-NEXT: [[R:%.*]] = or disjoint i32 [[SHR]], [[SHL]]1051; CHECK-NEXT: ret i32 [[R]]1052;1053 %sub = sub i32 33, %y1054 %shl = shl i32 %x, %y1055 %shr = lshr i32 %x, %sub1056 %r = add i32 %shr, %shl1057 ret i32 %r1058}1059 1060define i32 @rotr_i32_add_greater(i32 %x, i32 %y) {1061; CHECK-LABEL: @rotr_i32_add_greater(1062; CHECK-NEXT: [[SUB:%.*]] = sub i32 34, [[Y:%.*]]1063; CHECK-NEXT: [[SHL:%.*]] = lshr i32 [[X:%.*]], [[Y]]1064; CHECK-NEXT: [[SHR:%.*]] = shl i32 [[X]], [[SUB]]1065; CHECK-NEXT: [[R:%.*]] = or disjoint i32 [[SHR]], [[SHL]]1066; CHECK-NEXT: ret i32 [[R]]1067;1068 %sub = sub i32 34, %y1069 %shl = lshr i32 %x, %y1070 %shr = shl i32 %x, %sub1071 %r = add i32 %shr, %shl1072 ret i32 %r1073}1074 1075define i32 @not_rotl_i32_add_less(i32 %x, i32 %y) {1076; CHECK-LABEL: @not_rotl_i32_add_less(1077; CHECK-NEXT: [[SUB:%.*]] = sub i32 31, [[Y:%.*]]1078; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], [[Y]]1079; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X]], [[SUB]]1080; CHECK-NEXT: [[R:%.*]] = add i32 [[SHR]], [[SHL]]1081; CHECK-NEXT: ret i32 [[R]]1082;1083 %sub = sub i32 31, %y1084 %shl = shl i32 %x, %y1085 %shr = lshr i32 %x, %sub1086 %r = add i32 %shr, %shl1087 ret i32 %r1088}1089