676 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt -mtriple=amdgcn-- -mcpu=gfx1030 -passes=instcombine -S < %s | FileCheck %s3 4; test unary5 6define float @hoist_fneg_f32(float %arg) {7; CHECK-LABEL: define float @hoist_fneg_f32(8; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR0:[0-9]+]] {9; CHECK-NEXT: [[BB:.*:]]10; CHECK-NEXT: [[TMP0:%.*]] = call float @llvm.amdgcn.readfirstlane.f32(float [[ARG]])11; CHECK-NEXT: [[RFL:%.*]] = fneg float [[TMP0]]12; CHECK-NEXT: ret float [[RFL]]13;14bb:15 %val = fneg float %arg16 %rfl = call float @llvm.amdgcn.readfirstlane.f32(float %val)17 ret float %rfl18}19 20define double @hoist_fneg_f64(double %arg) {21; CHECK-LABEL: define double @hoist_fneg_f64(22; CHECK-SAME: double [[ARG:%.*]]) #[[ATTR0]] {23; CHECK-NEXT: [[BB:.*:]]24; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.amdgcn.readfirstlane.f64(double [[ARG]])25; CHECK-NEXT: [[RFL:%.*]] = fneg double [[TMP0]]26; CHECK-NEXT: ret double [[RFL]]27;28bb:29 %val = fneg double %arg30 %rfl = call double @llvm.amdgcn.readfirstlane.f64(double %val)31 ret double %rfl32}33 34; test casts35 36define i32 @hoist_trunc(i64 %arg) {37; CHECK-LABEL: define i32 @hoist_trunc(38; CHECK-SAME: i64 [[ARG:%.*]]) #[[ATTR0]] {39; CHECK-NEXT: [[BB:.*:]]40; CHECK-NEXT: [[RFL:%.*]] = call i64 @llvm.amdgcn.readfirstlane.i64(i64 [[ARG]])41; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[RFL]] to i3242; CHECK-NEXT: ret i32 [[TMP0]]43;44bb:45 %val = trunc i64 %arg to i3246 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)47 ret i32 %rfl48}49 50define i64 @hoist_zext(i32 %arg) {51; CHECK-LABEL: define i64 @hoist_zext(52; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {53; CHECK-NEXT: [[BB:.*:]]54; CHECK-NEXT: [[RFL:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])55; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[RFL]] to i6456; CHECK-NEXT: ret i64 [[TMP0]]57;58bb:59 %val = zext i32 %arg to i6460 %rfl = call i64 @llvm.amdgcn.readfirstlane.i64(i64 %val)61 ret i64 %rfl62}63 64define i64 @hoist_sext(i32 %arg) {65; CHECK-LABEL: define i64 @hoist_sext(66; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {67; CHECK-NEXT: [[BB:.*:]]68; CHECK-NEXT: [[RFL:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])69; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[RFL]] to i6470; CHECK-NEXT: ret i64 [[TMP0]]71;72bb:73 %val = zext i32 %arg to i6474 %rfl = call i64 @llvm.amdgcn.readfirstlane.i64(i64 %val)75 ret i64 %rfl76}77 78define i32 @hoist_fptoui(float %arg) {79; CHECK-LABEL: define i32 @hoist_fptoui(80; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR0]] {81; CHECK-NEXT: [[BB:.*:]]82; CHECK-NEXT: [[RFL:%.*]] = call float @llvm.amdgcn.readfirstlane.f32(float [[ARG]])83; CHECK-NEXT: [[TMP0:%.*]] = fptoui float [[RFL]] to i3284; CHECK-NEXT: ret i32 [[TMP0]]85;86bb:87 %val = fptoui float %arg to i3288 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)89 ret i32 %rfl90}91 92define i32 @hoist_fptosi(float %arg) {93; CHECK-LABEL: define i32 @hoist_fptosi(94; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR0]] {95; CHECK-NEXT: [[BB:.*:]]96; CHECK-NEXT: [[RFL:%.*]] = call float @llvm.amdgcn.readfirstlane.f32(float [[ARG]])97; CHECK-NEXT: [[TMP0:%.*]] = fptosi float [[RFL]] to i3298; CHECK-NEXT: ret i32 [[TMP0]]99;100bb:101 %val = fptosi float %arg to i32102 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)103 ret i32 %rfl104}105 106define float @hoist_uitofp(i32 %arg) {107; CHECK-LABEL: define float @hoist_uitofp(108; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {109; CHECK-NEXT: [[BB:.*:]]110; CHECK-NEXT: [[RFL:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])111; CHECK-NEXT: [[TMP0:%.*]] = uitofp i32 [[RFL]] to float112; CHECK-NEXT: ret float [[TMP0]]113;114bb:115 %val = uitofp i32 %arg to float116 %rfl = call float @llvm.amdgcn.readfirstlane.f32(float %val)117 ret float %rfl118}119 120define float @hoist_sitofp(i32 %arg) {121; CHECK-LABEL: define float @hoist_sitofp(122; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {123; CHECK-NEXT: [[BB:.*:]]124; CHECK-NEXT: [[RFL:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])125; CHECK-NEXT: [[TMP0:%.*]] = sitofp i32 [[RFL]] to float126; CHECK-NEXT: ret float [[TMP0]]127;128bb:129 %val = sitofp i32 %arg to float130 %rfl = call float @llvm.amdgcn.readfirstlane.f32(float %val)131 ret float %rfl132}133 134define float @hoist_fptrunc(double %arg) {135; CHECK-LABEL: define float @hoist_fptrunc(136; CHECK-SAME: double [[ARG:%.*]]) #[[ATTR0]] {137; CHECK-NEXT: [[BB:.*:]]138; CHECK-NEXT: [[RFL:%.*]] = call double @llvm.amdgcn.readfirstlane.f64(double [[ARG]])139; CHECK-NEXT: [[TMP0:%.*]] = fptrunc double [[RFL]] to float140; CHECK-NEXT: ret float [[TMP0]]141;142bb:143 %val = fptrunc double %arg to float144 %rfl = call float @llvm.amdgcn.readfirstlane.f32(float %val)145 ret float %rfl146}147 148define float @hoist_fpext(half %arg) {149; CHECK-LABEL: define float @hoist_fpext(150; CHECK-SAME: half [[ARG:%.*]]) #[[ATTR0]] {151; CHECK-NEXT: [[BB:.*:]]152; CHECK-NEXT: [[RFL:%.*]] = call half @llvm.amdgcn.readfirstlane.f16(half [[ARG]])153; CHECK-NEXT: [[TMP0:%.*]] = fpext half [[RFL]] to float154; CHECK-NEXT: ret float [[TMP0]]155;156bb:157 %val = fpext half %arg to float158 %rfl = call float @llvm.amdgcn.readfirstlane.f32(float %val)159 ret float %rfl160}161 162define i64 @hoist_ptrtoint(ptr %arg) {163; CHECK-LABEL: define i64 @hoist_ptrtoint(164; CHECK-SAME: ptr [[ARG:%.*]]) #[[ATTR0]] {165; CHECK-NEXT: [[BB:.*:]]166; CHECK-NEXT: [[RFL:%.*]] = call ptr @llvm.amdgcn.readfirstlane.p0(ptr [[ARG]])167; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[RFL]] to i64168; CHECK-NEXT: ret i64 [[TMP0]]169;170bb:171 %val = ptrtoint ptr %arg to i64172 %rfl = call i64 @llvm.amdgcn.readfirstlane.i64(i64 %val)173 ret i64 %rfl174}175 176define ptr @hoist_inttoptr(i64 %arg) {177; CHECK-LABEL: define ptr @hoist_inttoptr(178; CHECK-SAME: i64 [[ARG:%.*]]) #[[ATTR0]] {179; CHECK-NEXT: [[BB:.*:]]180; CHECK-NEXT: [[RFL:%.*]] = call i64 @llvm.amdgcn.readfirstlane.i64(i64 [[ARG]])181; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[RFL]] to ptr182; CHECK-NEXT: ret ptr [[TMP0]]183;184bb:185 %val = inttoptr i64 %arg to ptr186 %rfl = call ptr @llvm.amdgcn.readfirstlane.p0(ptr %val)187 ret ptr %rfl188}189 190define float @hoist_bitcast(i32 %arg) {191; CHECK-LABEL: define float @hoist_bitcast(192; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {193; CHECK-NEXT: [[BB:.*:]]194; CHECK-NEXT: [[RFL:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])195; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32 [[RFL]] to float196; CHECK-NEXT: ret float [[TMP0]]197;198bb:199 %val = bitcast i32 %arg to float200 %rfl = call float @llvm.amdgcn.readfirstlane.f32(float %val)201 ret float %rfl202}203 204define ptr addrspace(1) @hoist_addrspacecast(ptr addrspace(0) %arg) {205; CHECK-LABEL: define ptr addrspace(1) @hoist_addrspacecast(206; CHECK-SAME: ptr [[ARG:%.*]]) #[[ATTR0]] {207; CHECK-NEXT: [[BB:.*:]]208; CHECK-NEXT: [[RFL:%.*]] = call ptr @llvm.amdgcn.readfirstlane.p0(ptr [[ARG]])209; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[RFL]] to ptr addrspace(1)210; CHECK-NEXT: ret ptr addrspace(1) [[TMP0]]211;212bb:213 %val = addrspacecast ptr addrspace(0) %arg to ptr addrspace(1)214 %rfl = call ptr addrspace(1) @llvm.amdgcn.readfirstlane.p1(ptr addrspace(1) %val)215 ret ptr addrspace(1) %rfl216}217 218; test binary i32219 220define i32 @hoist_add_i32(i32 %arg) {221; CHECK-LABEL: define i32 @hoist_add_i32(222; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {223; CHECK-NEXT: [[BB:.*:]]224; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])225; CHECK-NEXT: [[RFL:%.*]] = add i32 [[TMP0]], 16777215226; CHECK-NEXT: ret i32 [[RFL]]227;228bb:229 %val = add i32 %arg, 16777215230 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)231 ret i32 %rfl232}233 234define float @hoist_fadd_f32(float %arg) {235; CHECK-LABEL: define float @hoist_fadd_f32(236; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR0]] {237; CHECK-NEXT: [[BB:.*:]]238; CHECK-NEXT: [[TMP0:%.*]] = call float @llvm.amdgcn.readfirstlane.f32(float [[ARG]])239; CHECK-NEXT: [[RFL:%.*]] = fadd float [[TMP0]], 1.280000e+02240; CHECK-NEXT: ret float [[RFL]]241;242bb:243 %val = fadd float %arg, 128.0244 %rfl = call float @llvm.amdgcn.readfirstlane.f32(float %val)245 ret float %rfl246}247 248define i32 @hoist_sub_i32(i32 %arg) {249; CHECK-LABEL: define i32 @hoist_sub_i32(250; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {251; CHECK-NEXT: [[BB:.*:]]252; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])253; CHECK-NEXT: [[RFL:%.*]] = add i32 [[TMP0]], -16777215254; CHECK-NEXT: ret i32 [[RFL]]255;256bb:257 %val = sub i32 %arg, 16777215258 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)259 ret i32 %rfl260}261 262define float @hoist_fsub_f32(float %arg) {263; CHECK-LABEL: define float @hoist_fsub_f32(264; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR0]] {265; CHECK-NEXT: [[BB:.*:]]266; CHECK-NEXT: [[TMP0:%.*]] = call float @llvm.amdgcn.readfirstlane.f32(float [[ARG]])267; CHECK-NEXT: [[RFL:%.*]] = fadd float [[TMP0]], -1.280000e+02268; CHECK-NEXT: ret float [[RFL]]269;270bb:271 %val = fsub float %arg, 128.0272 %rfl = call float @llvm.amdgcn.readfirstlane.f32(float %val)273 ret float %rfl274}275 276define i32 @hoist_mul_i32(i32 %arg) {277; CHECK-LABEL: define i32 @hoist_mul_i32(278; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {279; CHECK-NEXT: [[BB:.*:]]280; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])281; CHECK-NEXT: [[RFL:%.*]] = mul i32 [[TMP0]], 16777215282; CHECK-NEXT: ret i32 [[RFL]]283;284bb:285 %val = mul i32 %arg, 16777215286 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)287 ret i32 %rfl288}289 290define float @hoist_fmul_f32(float %arg) {291; CHECK-LABEL: define float @hoist_fmul_f32(292; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR0]] {293; CHECK-NEXT: [[BB:.*:]]294; CHECK-NEXT: [[TMP0:%.*]] = call float @llvm.amdgcn.readfirstlane.f32(float [[ARG]])295; CHECK-NEXT: [[RFL:%.*]] = fmul float [[TMP0]], 1.280000e+02296; CHECK-NEXT: ret float [[RFL]]297;298bb:299 %val = fmul float %arg, 128.0300 %rfl = call float @llvm.amdgcn.readfirstlane.f32(float %val)301 ret float %rfl302}303 304define i32 @hoist_udiv_i32(i32 %arg) {305; CHECK-LABEL: define i32 @hoist_udiv_i32(306; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {307; CHECK-NEXT: [[BB:.*:]]308; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])309; CHECK-NEXT: [[RFL:%.*]] = udiv i32 [[TMP0]], 16777215310; CHECK-NEXT: ret i32 [[RFL]]311;312bb:313 %val = udiv i32 %arg, 16777215314 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)315 ret i32 %rfl316}317 318define i32 @hoist_sdiv_i32(i32 %arg) {319; CHECK-LABEL: define i32 @hoist_sdiv_i32(320; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {321; CHECK-NEXT: [[BB:.*:]]322; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])323; CHECK-NEXT: [[RFL:%.*]] = sdiv i32 [[TMP0]], 16777215324; CHECK-NEXT: ret i32 [[RFL]]325;326bb:327 %val = sdiv i32 %arg, 16777215328 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)329 ret i32 %rfl330}331 332define float @hoist_fdiv_f32(float %arg) {333; CHECK-LABEL: define float @hoist_fdiv_f32(334; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR0]] {335; CHECK-NEXT: [[BB:.*:]]336; CHECK-NEXT: [[TMP0:%.*]] = call float @llvm.amdgcn.readfirstlane.f32(float [[ARG]])337; CHECK-NEXT: [[RFL:%.*]] = fmul float [[TMP0]], 7.812500e-03338; CHECK-NEXT: ret float [[RFL]]339;340bb:341 %val = fdiv float %arg, 128.0342 %rfl = call float @llvm.amdgcn.readfirstlane.f32(float %val)343 ret float %rfl344}345 346define i32 @hoist_urem_i32(i32 %arg) {347; CHECK-LABEL: define i32 @hoist_urem_i32(348; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {349; CHECK-NEXT: [[BB:.*:]]350; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])351; CHECK-NEXT: [[RFL:%.*]] = urem i32 [[TMP0]], 16777215352; CHECK-NEXT: ret i32 [[RFL]]353;354bb:355 %val = urem i32 %arg, 16777215356 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)357 ret i32 %rfl358}359 360define i32 @hoist_srem_i32(i32 %arg) {361; CHECK-LABEL: define i32 @hoist_srem_i32(362; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {363; CHECK-NEXT: [[BB:.*:]]364; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])365; CHECK-NEXT: [[RFL:%.*]] = srem i32 [[TMP0]], 16777215366; CHECK-NEXT: ret i32 [[RFL]]367;368bb:369 %val = srem i32 %arg, 16777215370 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)371 ret i32 %rfl372}373 374define float @hoist_frem_f32(float %arg) {375; CHECK-LABEL: define float @hoist_frem_f32(376; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR0]] {377; CHECK-NEXT: [[BB:.*:]]378; CHECK-NEXT: [[TMP0:%.*]] = call float @llvm.amdgcn.readfirstlane.f32(float [[ARG]])379; CHECK-NEXT: [[RFL:%.*]] = frem float [[TMP0]], 1.280000e+02380; CHECK-NEXT: ret float [[RFL]]381;382bb:383 %val = frem float %arg, 128.0384 %rfl = call float @llvm.amdgcn.readfirstlane.f32(float %val)385 ret float %rfl386}387 388define i32 @hoist_shl_i32(i32 %arg) {389; CHECK-LABEL: define i32 @hoist_shl_i32(390; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {391; CHECK-NEXT: [[BB:.*:]]392; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])393; CHECK-NEXT: [[RFL:%.*]] = shl i32 [[TMP0]], 4394; CHECK-NEXT: ret i32 [[RFL]]395;396bb:397 %val = shl i32 %arg, 4398 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)399 ret i32 %rfl400}401 402define i32 @hoist_lshr_i32(i32 %arg) {403; CHECK-LABEL: define i32 @hoist_lshr_i32(404; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {405; CHECK-NEXT: [[BB:.*:]]406; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])407; CHECK-NEXT: [[RFL:%.*]] = lshr i32 [[TMP0]], 4408; CHECK-NEXT: ret i32 [[RFL]]409;410bb:411 %val = lshr i32 %arg, 4412 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)413 ret i32 %rfl414}415 416define i32 @hoist_ashr_i32(i32 %arg) {417; CHECK-LABEL: define i32 @hoist_ashr_i32(418; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {419; CHECK-NEXT: [[BB:.*:]]420; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])421; CHECK-NEXT: [[RFL:%.*]] = ashr i32 [[TMP0]], 4422; CHECK-NEXT: ret i32 [[RFL]]423;424bb:425 %val = ashr i32 %arg, 4426 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)427 ret i32 %rfl428}429 430 431define i32 @hoist_and_i32(i32 %arg) {432; CHECK-LABEL: define i32 @hoist_and_i32(433; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {434; CHECK-NEXT: [[BB:.*:]]435; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])436; CHECK-NEXT: [[RFL:%.*]] = and i32 [[TMP0]], 16777215437; CHECK-NEXT: ret i32 [[RFL]]438;439bb:440 %val = and i32 %arg, 16777215441 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)442 ret i32 %rfl443}444 445define i32 @hoist_or_i32(i32 %arg) {446; CHECK-LABEL: define i32 @hoist_or_i32(447; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {448; CHECK-NEXT: [[BB:.*:]]449; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])450; CHECK-NEXT: [[RFL:%.*]] = or i32 [[TMP0]], 16777215451; CHECK-NEXT: ret i32 [[RFL]]452;453bb:454 %val = or i32 %arg, 16777215455 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)456 ret i32 %rfl457}458 459define i32 @hoist_xor_i32(i32 %arg) {460; CHECK-LABEL: define i32 @hoist_xor_i32(461; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {462; CHECK-NEXT: [[BB:.*:]]463; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])464; CHECK-NEXT: [[RFL:%.*]] = xor i32 [[TMP0]], 16777215465; CHECK-NEXT: ret i32 [[RFL]]466;467bb:468 %val = xor i32 %arg, 16777215469 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)470 ret i32 %rfl471}472 473; test binary i64474 475define i64 @hoist_and_i64(i64 %arg) {476; CHECK-LABEL: define i64 @hoist_and_i64(477; CHECK-SAME: i64 [[ARG:%.*]]) #[[ATTR0]] {478; CHECK-NEXT: [[BB:.*:]]479; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.amdgcn.readfirstlane.i64(i64 [[ARG]])480; CHECK-NEXT: [[RFL:%.*]] = and i64 [[TMP0]], 16777215481; CHECK-NEXT: ret i64 [[RFL]]482;483bb:484 %val = and i64 %arg, 16777215485 %rfl = call i64 @llvm.amdgcn.readfirstlane.i32(i64 %val)486 ret i64 %rfl487}488 489define double @hoist_fadd_f64(double %arg) {490; CHECK-LABEL: define double @hoist_fadd_f64(491; CHECK-SAME: double [[ARG:%.*]]) #[[ATTR0]] {492; CHECK-NEXT: [[BB:.*:]]493; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.amdgcn.readfirstlane.f64(double [[ARG]])494; CHECK-NEXT: [[RFL:%.*]] = fadd double [[TMP0]], 1.280000e+02495; CHECK-NEXT: ret double [[RFL]]496;497bb:498 %val = fadd double %arg, 128.0499 %rfl = call double @llvm.amdgcn.readfirstlane.f64(double %val)500 ret double %rfl501}502 503; test constant on LHS504 505define i32 @hoist_sub_i32_lhs(i32 %arg) {506; CHECK-LABEL: define i32 @hoist_sub_i32_lhs(507; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {508; CHECK-NEXT: [[BB:.*:]]509; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])510; CHECK-NEXT: [[RFL:%.*]] = sub i32 16777215, [[TMP0]]511; CHECK-NEXT: ret i32 [[RFL]]512;513bb:514 %val = sub i32 16777215, %arg515 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)516 ret i32 %rfl517}518 519define float @hoist_fsub_f32_lhs(float %arg) {520; CHECK-LABEL: define float @hoist_fsub_f32_lhs(521; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR0]] {522; CHECK-NEXT: [[BB:.*:]]523; CHECK-NEXT: [[TMP0:%.*]] = call float @llvm.amdgcn.readfirstlane.f32(float [[ARG]])524; CHECK-NEXT: [[RFL:%.*]] = fsub float 1.280000e+02, [[TMP0]]525; CHECK-NEXT: ret float [[RFL]]526;527bb:528 %val = fsub float 128.0, %arg529 %rfl = call float @llvm.amdgcn.readfirstlane.f32(float %val)530 ret float %rfl531}532 533; test other operand is trivially uniform534 535define i32 @hoist_add_i32_trivially_uniform_rhs(i32 %arg, i32 %v.other) {536; CHECK-LABEL: define i32 @hoist_add_i32_trivially_uniform_rhs(537; CHECK-SAME: i32 [[ARG:%.*]], i32 [[V_OTHER:%.*]]) #[[ATTR0]] {538; CHECK-NEXT: [[BB:.*:]]539; CHECK-NEXT: [[OTHER:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[V_OTHER]])540; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])541; CHECK-NEXT: [[RFL:%.*]] = add i32 [[TMP0]], [[OTHER]]542; CHECK-NEXT: ret i32 [[RFL]]543;544bb:545 %other = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %v.other)546 %val = add i32 %arg, %other547 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)548 ret i32 %rfl549}550 551define i32 @hoist_add_i32_trivially_uniform_lhs(i32 %arg, i32 %v.other) {552; CHECK-LABEL: define i32 @hoist_add_i32_trivially_uniform_lhs(553; CHECK-SAME: i32 [[ARG:%.*]], i32 [[V_OTHER:%.*]]) #[[ATTR0]] {554; CHECK-NEXT: [[BB:.*:]]555; CHECK-NEXT: [[OTHER:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[V_OTHER]])556; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])557; CHECK-NEXT: [[RFL:%.*]] = sub i32 [[OTHER]], [[TMP0]]558; CHECK-NEXT: ret i32 [[RFL]]559;560bb:561 %other = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %v.other)562 %val = sub i32 %other, %arg563 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)564 ret i32 %rfl565}566 567; test multiple iterations568 569define i32 @hoist_multiple_times(i32 %arg) {570; CHECK-LABEL: define i32 @hoist_multiple_times(571; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] {572; CHECK-NEXT: [[BB:.*:]]573; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]])574; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[TMP0]], 2575; CHECK-NEXT: [[TMP2:%.*]] = sub i32 16777215, [[TMP1]]576; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], 4242577; CHECK-NEXT: [[RFL:%.*]] = add i32 [[TMP3]], 6578; CHECK-NEXT: ret i32 [[RFL]]579;580bb:581 %val.0 = shl i32 %arg, 2582 %val.1 = sub i32 16777215, %val.0583 %val.2 = xor i32 %val.1, 4242584 %val.3 = add i32 %val.2, 6585 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val.3)586 ret i32 %rfl587}588 589; test cases where hoisting isn't possible590 591define i32 @cross_block_hoisting(i1 %cond, i32 %arg) {592; CHECK-LABEL: define i32 @cross_block_hoisting(593; CHECK-SAME: i1 [[COND:%.*]], i32 [[ARG:%.*]]) #[[ATTR0]] {594; CHECK-NEXT: [[BB:.*]]:595; CHECK-NEXT: [[VAL:%.*]] = add i32 [[ARG]], 16777215596; CHECK-NEXT: br i1 [[COND]], label %[[THEN:.*]], label %[[END:.*]]597; CHECK: [[THEN]]:598; CHECK-NEXT: [[RFL:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[VAL]])599; CHECK-NEXT: br label %[[END]]600; CHECK: [[END]]:601; CHECK-NEXT: [[RES:%.*]] = phi i32 [ [[RFL]], %[[THEN]] ], [ [[VAL]], %[[BB]] ]602; CHECK-NEXT: ret i32 [[RES]]603;604bb:605 %val = add i32 %arg, 16777215606 br i1 %cond, label %then, label %end607 608then:609 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)610 br label %end611 612end:613 %res = phi i32 [%rfl, %then], [%val, %bb]614 ret i32 %res615}616 617define i32 @operand_is_instr(i32 %arg, ptr %src) {618; CHECK-LABEL: define i32 @operand_is_instr(619; CHECK-SAME: i32 [[ARG:%.*]], ptr [[SRC:%.*]]) #[[ATTR0]] {620; CHECK-NEXT: [[BB:.*:]]621; CHECK-NEXT: [[OTHER:%.*]] = load i32, ptr [[SRC]], align 4622; CHECK-NEXT: [[VAL:%.*]] = add i32 [[ARG]], [[OTHER]]623; CHECK-NEXT: [[RFL:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[VAL]])624; CHECK-NEXT: ret i32 [[RFL]]625;626bb:627 %other = load i32, ptr %src628 %val = add i32 %arg, %other629 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)630 ret i32 %rfl631}632 633define i32 @operand_is_arg(i32 %arg, i32 %other) {634; CHECK-LABEL: define i32 @operand_is_arg(635; CHECK-SAME: i32 [[ARG:%.*]], i32 [[OTHER:%.*]]) #[[ATTR0]] {636; CHECK-NEXT: [[BB:.*:]]637; CHECK-NEXT: [[VAL:%.*]] = add i32 [[ARG]], [[OTHER]]638; CHECK-NEXT: [[RFL:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[VAL]])639; CHECK-NEXT: ret i32 [[RFL]]640;641bb:642 %val = add i32 %arg, %other643 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val)644 ret i32 %rfl645}646 647; test that convergence tokens are preserved648 649define i32 @hoist_preserves_convergence_token(i1 %cond, i32 %arg) convergent {650; CHECK-LABEL: define i32 @hoist_preserves_convergence_token(651; CHECK-SAME: i1 [[COND:%.*]], i32 [[ARG:%.*]]) #[[ATTR1:[0-9]+]] {652; CHECK-NEXT: [[BB:.*]]:653; CHECK-NEXT: [[ENTRY:%.*]] = call token @llvm.experimental.convergence.entry()654; CHECK-NEXT: br i1 [[COND]], label %[[THEN:.*]], label %[[END:.*]]655; CHECK: [[THEN]]:656; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[ARG]]) [ "convergencectrl"(token [[ENTRY]]) ]657; CHECK-NEXT: [[RFL:%.*]] = add i32 [[TMP0]], 16777215658; CHECK-NEXT: br label %[[END]]659; CHECK: [[END]]:660; CHECK-NEXT: [[RES:%.*]] = phi i32 [ [[RFL]], %[[THEN]] ], [ [[ARG]], %[[BB]] ]661; CHECK-NEXT: ret i32 [[RES]]662;663bb:664 %entry = call token @llvm.experimental.convergence.entry()665 br i1 %cond, label %then, label %end666 667then:668 %val = add i32 %arg, 16777215669 %rfl = call i32 @llvm.amdgcn.readfirstlane.i32(i32 %val) [ "convergencectrl"(token %entry)]670 br label %end671 672end:673 %res = phi i32 [%rfl, %then], [%arg, %bb]674 ret i32 %res675}676