470 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=riscv64 -global-isel -verify-machineinstrs < %s \3; RUN: | FileCheck %s -check-prefixes=CHECK,RV64I4; RUN: llc -mtriple=riscv64 -global-isel -mattr=+zbb -verify-machineinstrs < %s \5; RUN: | FileCheck %s -check-prefixes=CHECK,RV64ZBB-ZBKB,RV64ZBB6; RUN: llc -mtriple=riscv64 -global-isel -mattr=+zbkb -verify-machineinstrs < %s \7; RUN: | FileCheck %s -check-prefixes=CHECK,RV64ZBB-ZBKB,RV64ZBKB8 9define signext i32 @andn_i32(i32 signext %a, i32 signext %b) nounwind {10; RV64I-LABEL: andn_i32:11; RV64I: # %bb.0:12; RV64I-NEXT: not a1, a113; RV64I-NEXT: and a0, a1, a014; RV64I-NEXT: ret15;16; RV64ZBB-ZBKB-LABEL: andn_i32:17; RV64ZBB-ZBKB: # %bb.0:18; RV64ZBB-ZBKB-NEXT: andn a0, a0, a119; RV64ZBB-ZBKB-NEXT: ret20 %neg = xor i32 %b, -121 %and = and i32 %neg, %a22 ret i32 %and23}24 25define i64 @andn_i64(i64 %a, i64 %b) nounwind {26; RV64I-LABEL: andn_i64:27; RV64I: # %bb.0:28; RV64I-NEXT: not a1, a129; RV64I-NEXT: and a0, a1, a030; RV64I-NEXT: ret31;32; RV64ZBB-ZBKB-LABEL: andn_i64:33; RV64ZBB-ZBKB: # %bb.0:34; RV64ZBB-ZBKB-NEXT: andn a0, a0, a135; RV64ZBB-ZBKB-NEXT: ret36 %neg = xor i64 %b, -137 %and = and i64 %neg, %a38 ret i64 %and39}40 41define signext i32 @orn_i32(i32 signext %a, i32 signext %b) nounwind {42; RV64I-LABEL: orn_i32:43; RV64I: # %bb.0:44; RV64I-NEXT: not a1, a145; RV64I-NEXT: or a0, a1, a046; RV64I-NEXT: ret47;48; RV64ZBB-ZBKB-LABEL: orn_i32:49; RV64ZBB-ZBKB: # %bb.0:50; RV64ZBB-ZBKB-NEXT: orn a0, a0, a151; RV64ZBB-ZBKB-NEXT: ret52 %neg = xor i32 %b, -153 %or = or i32 %neg, %a54 ret i32 %or55}56 57define i64 @orn_i64(i64 %a, i64 %b) nounwind {58; RV64I-LABEL: orn_i64:59; RV64I: # %bb.0:60; RV64I-NEXT: not a1, a161; RV64I-NEXT: or a0, a1, a062; RV64I-NEXT: ret63;64; RV64ZBB-ZBKB-LABEL: orn_i64:65; RV64ZBB-ZBKB: # %bb.0:66; RV64ZBB-ZBKB-NEXT: orn a0, a0, a167; RV64ZBB-ZBKB-NEXT: ret68 %neg = xor i64 %b, -169 %or = or i64 %neg, %a70 ret i64 %or71}72 73define signext i32 @xnor_i32(i32 signext %a, i32 signext %b) nounwind {74; RV64I-LABEL: xnor_i32:75; RV64I: # %bb.0:76; RV64I-NEXT: not a0, a077; RV64I-NEXT: xor a0, a0, a178; RV64I-NEXT: ret79;80; RV64ZBB-ZBKB-LABEL: xnor_i32:81; RV64ZBB-ZBKB: # %bb.0:82; RV64ZBB-ZBKB-NEXT: xnor a0, a0, a183; RV64ZBB-ZBKB-NEXT: ret84 %neg = xor i32 %a, -185 %xor = xor i32 %neg, %b86 ret i32 %xor87}88 89define i64 @xnor_i64(i64 %a, i64 %b) nounwind {90; RV64I-LABEL: xnor_i64:91; RV64I: # %bb.0:92; RV64I-NEXT: not a0, a093; RV64I-NEXT: xor a0, a0, a194; RV64I-NEXT: ret95;96; RV64ZBB-ZBKB-LABEL: xnor_i64:97; RV64ZBB-ZBKB: # %bb.0:98; RV64ZBB-ZBKB-NEXT: xnor a0, a0, a199; RV64ZBB-ZBKB-NEXT: ret100 %neg = xor i64 %a, -1101 %xor = xor i64 %neg, %b102 ret i64 %xor103}104 105define signext i32 @rol_i32(i32 signext %a, i32 signext %b) nounwind {106; RV64I-LABEL: rol_i32:107; RV64I: # %bb.0:108; RV64I-NEXT: neg a2, a1109; RV64I-NEXT: sllw a1, a0, a1110; RV64I-NEXT: srlw a0, a0, a2111; RV64I-NEXT: or a0, a1, a0112; RV64I-NEXT: ret113;114; RV64ZBB-ZBKB-LABEL: rol_i32:115; RV64ZBB-ZBKB: # %bb.0:116; RV64ZBB-ZBKB-NEXT: rolw a0, a0, a1117; RV64ZBB-ZBKB-NEXT: ret118 %1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 %b)119 ret i32 %1120}121 122; Similar to rol_i32, but doesn't sign extend the result.123define void @rol_i32_nosext(i32 signext %a, i32 signext %b, ptr %x) nounwind {124; RV64I-LABEL: rol_i32_nosext:125; RV64I: # %bb.0:126; RV64I-NEXT: neg a3, a1127; RV64I-NEXT: sllw a1, a0, a1128; RV64I-NEXT: srlw a0, a0, a3129; RV64I-NEXT: or a0, a1, a0130; RV64I-NEXT: sw a0, 0(a2)131; RV64I-NEXT: ret132;133; RV64ZBB-ZBKB-LABEL: rol_i32_nosext:134; RV64ZBB-ZBKB: # %bb.0:135; RV64ZBB-ZBKB-NEXT: rolw a0, a0, a1136; RV64ZBB-ZBKB-NEXT: sw a0, 0(a2)137; RV64ZBB-ZBKB-NEXT: ret138 %1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 %b)139 store i32 %1, ptr %x140 ret void141}142 143define signext i32 @rol_i32_neg_constant_rhs(i32 signext %a) nounwind {144; RV64I-LABEL: rol_i32_neg_constant_rhs:145; RV64I: # %bb.0:146; RV64I-NEXT: li a1, -2147; RV64I-NEXT: neg a2, a0148; RV64I-NEXT: sllw a0, a1, a0149; RV64I-NEXT: srlw a1, a1, a2150; RV64I-NEXT: or a0, a0, a1151; RV64I-NEXT: ret152;153; RV64ZBB-ZBKB-LABEL: rol_i32_neg_constant_rhs:154; RV64ZBB-ZBKB: # %bb.0:155; RV64ZBB-ZBKB-NEXT: li a1, -2156; RV64ZBB-ZBKB-NEXT: rolw a0, a1, a0157; RV64ZBB-ZBKB-NEXT: ret158 %1 = tail call i32 @llvm.fshl.i32(i32 -2, i32 -2, i32 %a)159 ret i32 %1160}161 162define i64 @rol_i64(i64 %a, i64 %b) nounwind {163; RV64I-LABEL: rol_i64:164; RV64I: # %bb.0:165; RV64I-NEXT: neg a2, a1166; RV64I-NEXT: sll a1, a0, a1167; RV64I-NEXT: srl a0, a0, a2168; RV64I-NEXT: or a0, a1, a0169; RV64I-NEXT: ret170;171; RV64ZBB-ZBKB-LABEL: rol_i64:172; RV64ZBB-ZBKB: # %bb.0:173; RV64ZBB-ZBKB-NEXT: rol a0, a0, a1174; RV64ZBB-ZBKB-NEXT: ret175 %or = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 %b)176 ret i64 %or177}178 179define signext i32 @ror_i32(i32 signext %a, i32 signext %b) nounwind {180; RV64I-LABEL: ror_i32:181; RV64I: # %bb.0:182; RV64I-NEXT: neg a2, a1183; RV64I-NEXT: srlw a1, a0, a1184; RV64I-NEXT: sllw a0, a0, a2185; RV64I-NEXT: or a0, a1, a0186; RV64I-NEXT: ret187;188; RV64ZBB-ZBKB-LABEL: ror_i32:189; RV64ZBB-ZBKB: # %bb.0:190; RV64ZBB-ZBKB-NEXT: rorw a0, a0, a1191; RV64ZBB-ZBKB-NEXT: ret192 %1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 %b)193 ret i32 %1194}195 196; Similar to ror_i32, but doesn't sign extend the result.197define void @ror_i32_nosext(i32 signext %a, i32 signext %b, ptr %x) nounwind {198; RV64I-LABEL: ror_i32_nosext:199; RV64I: # %bb.0:200; RV64I-NEXT: neg a3, a1201; RV64I-NEXT: srlw a1, a0, a1202; RV64I-NEXT: sllw a0, a0, a3203; RV64I-NEXT: or a0, a1, a0204; RV64I-NEXT: sw a0, 0(a2)205; RV64I-NEXT: ret206;207; RV64ZBB-ZBKB-LABEL: ror_i32_nosext:208; RV64ZBB-ZBKB: # %bb.0:209; RV64ZBB-ZBKB-NEXT: rorw a0, a0, a1210; RV64ZBB-ZBKB-NEXT: sw a0, 0(a2)211; RV64ZBB-ZBKB-NEXT: ret212 %1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 %b)213 store i32 %1, ptr %x214 ret void215}216 217define signext i32 @ror_i32_neg_constant_rhs(i32 signext %a) nounwind {218; RV64I-LABEL: ror_i32_neg_constant_rhs:219; RV64I: # %bb.0:220; RV64I-NEXT: li a1, -2221; RV64I-NEXT: neg a2, a0222; RV64I-NEXT: srlw a0, a1, a0223; RV64I-NEXT: sllw a1, a1, a2224; RV64I-NEXT: or a0, a0, a1225; RV64I-NEXT: ret226;227; RV64ZBB-ZBKB-LABEL: ror_i32_neg_constant_rhs:228; RV64ZBB-ZBKB: # %bb.0:229; RV64ZBB-ZBKB-NEXT: li a1, -2230; RV64ZBB-ZBKB-NEXT: rorw a0, a1, a0231; RV64ZBB-ZBKB-NEXT: ret232 %1 = tail call i32 @llvm.fshr.i32(i32 -2, i32 -2, i32 %a)233 ret i32 %1234}235 236define i64 @ror_i64(i64 %a, i64 %b) nounwind {237; RV64I-LABEL: ror_i64:238; RV64I: # %bb.0:239; RV64I-NEXT: neg a2, a1240; RV64I-NEXT: srl a1, a0, a1241; RV64I-NEXT: sll a0, a0, a2242; RV64I-NEXT: or a0, a1, a0243; RV64I-NEXT: ret244;245; RV64ZBB-ZBKB-LABEL: ror_i64:246; RV64ZBB-ZBKB: # %bb.0:247; RV64ZBB-ZBKB-NEXT: ror a0, a0, a1248; RV64ZBB-ZBKB-NEXT: ret249 %or = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 %b)250 ret i64 %or251}252 253define signext i32 @rori_i32_fshl(i32 signext %a) nounwind {254; RV64I-LABEL: rori_i32_fshl:255; RV64I: # %bb.0:256; RV64I-NEXT: slliw a1, a0, 31257; RV64I-NEXT: srliw a0, a0, 1258; RV64I-NEXT: or a0, a1, a0259; RV64I-NEXT: ret260;261; RV64ZBB-ZBKB-LABEL: rori_i32_fshl:262; RV64ZBB-ZBKB: # %bb.0:263; RV64ZBB-ZBKB-NEXT: roriw a0, a0, 1264; RV64ZBB-ZBKB-NEXT: ret265 %1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 31)266 ret i32 %1267}268 269; Similar to rori_i32_fshl, but doesn't sign extend the result.270define void @rori_i32_fshl_nosext(i32 signext %a, ptr %x) nounwind {271; RV64I-LABEL: rori_i32_fshl_nosext:272; RV64I: # %bb.0:273; RV64I-NEXT: slli a2, a0, 31274; RV64I-NEXT: srliw a0, a0, 1275; RV64I-NEXT: or a0, a2, a0276; RV64I-NEXT: sw a0, 0(a1)277; RV64I-NEXT: ret278;279; RV64ZBB-ZBKB-LABEL: rori_i32_fshl_nosext:280; RV64ZBB-ZBKB: # %bb.0:281; RV64ZBB-ZBKB-NEXT: roriw a0, a0, 1282; RV64ZBB-ZBKB-NEXT: sw a0, 0(a1)283; RV64ZBB-ZBKB-NEXT: ret284 %1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 31)285 store i32 %1, ptr %x286 ret void287}288 289define signext i32 @rori_i32_fshr(i32 signext %a) nounwind {290; RV64I-LABEL: rori_i32_fshr:291; RV64I: # %bb.0:292; RV64I-NEXT: srliw a1, a0, 31293; RV64I-NEXT: slliw a0, a0, 1294; RV64I-NEXT: or a0, a1, a0295; RV64I-NEXT: ret296;297; RV64ZBB-ZBKB-LABEL: rori_i32_fshr:298; RV64ZBB-ZBKB: # %bb.0:299; RV64ZBB-ZBKB-NEXT: roriw a0, a0, 31300; RV64ZBB-ZBKB-NEXT: ret301 %1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 31)302 ret i32 %1303}304 305; Similar to rori_i32_fshr, but doesn't sign extend the result.306define void @rori_i32_fshr_nosext(i32 signext %a, ptr %x) nounwind {307; RV64I-LABEL: rori_i32_fshr_nosext:308; RV64I: # %bb.0:309; RV64I-NEXT: srliw a2, a0, 31310; RV64I-NEXT: slli a0, a0, 1311; RV64I-NEXT: or a0, a2, a0312; RV64I-NEXT: sw a0, 0(a1)313; RV64I-NEXT: ret314;315; RV64ZBB-ZBKB-LABEL: rori_i32_fshr_nosext:316; RV64ZBB-ZBKB: # %bb.0:317; RV64ZBB-ZBKB-NEXT: roriw a0, a0, 31318; RV64ZBB-ZBKB-NEXT: sw a0, 0(a1)319; RV64ZBB-ZBKB-NEXT: ret320 %1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 31)321 store i32 %1, ptr %x322 ret void323}324 325; This test is similar to the type legalized version of the fshl/fshr tests, but326; instead of having the same input to both shifts it has different inputs. Make327; sure we don't match it as a roriw.328define signext i32 @not_rori_i32(i32 signext %x, i32 signext %y) nounwind {329; CHECK-LABEL: not_rori_i32:330; CHECK: # %bb.0:331; CHECK-NEXT: slliw a0, a0, 31332; CHECK-NEXT: srliw a1, a1, 1333; CHECK-NEXT: or a0, a0, a1334; CHECK-NEXT: ret335 %a = shl i32 %x, 31336 %b = lshr i32 %y, 1337 %c = or i32 %a, %b338 ret i32 %c339}340 341; This is similar to the type legalized roriw pattern, but the and mask is more342; than 32 bits so the lshr doesn't shift zeroes into the lower 32 bits. Make343; sure we don't match it to roriw.344define i64 @roriw_bug(i64 %x) nounwind {345; CHECK-LABEL: roriw_bug:346; CHECK: # %bb.0:347; CHECK-NEXT: andi a1, a0, -2348; CHECK-NEXT: srli a2, a1, 1349; CHECK-NEXT: slli a0, a0, 63350; CHECK-NEXT: slli a2, a2, 32351; CHECK-NEXT: or a0, a0, a2352; CHECK-NEXT: srai a0, a0, 32353; CHECK-NEXT: xor a0, a1, a0354; CHECK-NEXT: ret355 %a = shl i64 %x, 31356 %b = and i64 %x, 18446744073709551614357 %c = lshr i64 %b, 1358 %d = or i64 %a, %c359 %e = shl i64 %d, 32360 %f = ashr i64 %e, 32361 %g = xor i64 %b, %f ; to increase the use count on %b to disable SimplifyDemandedBits.362 ret i64 %g363}364 365define i64 @rori_i64_fshl(i64 %a) nounwind {366; RV64I-LABEL: rori_i64_fshl:367; RV64I: # %bb.0:368; RV64I-NEXT: slli a1, a0, 63369; RV64I-NEXT: srli a0, a0, 1370; RV64I-NEXT: or a0, a1, a0371; RV64I-NEXT: ret372;373; RV64ZBB-ZBKB-LABEL: rori_i64_fshl:374; RV64ZBB-ZBKB: # %bb.0:375; RV64ZBB-ZBKB-NEXT: rori a0, a0, 1376; RV64ZBB-ZBKB-NEXT: ret377 %1 = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 63)378 ret i64 %1379}380 381define i64 @rori_i64_fshr(i64 %a) nounwind {382; RV64I-LABEL: rori_i64_fshr:383; RV64I: # %bb.0:384; RV64I-NEXT: srli a1, a0, 63385; RV64I-NEXT: slli a0, a0, 1386; RV64I-NEXT: or a0, a1, a0387; RV64I-NEXT: ret388;389; RV64ZBB-ZBKB-LABEL: rori_i64_fshr:390; RV64ZBB-ZBKB: # %bb.0:391; RV64ZBB-ZBKB-NEXT: rori a0, a0, 63392; RV64ZBB-ZBKB-NEXT: ret393 %1 = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 63)394 ret i64 %1395}396 397define i8 @srli_i8(i8 %a) nounwind {398; CHECK-LABEL: srli_i8:399; CHECK: # %bb.0:400; CHECK-NEXT: zext.b a0, a0401; CHECK-NEXT: srli a0, a0, 6402; CHECK-NEXT: ret403 %1 = lshr i8 %a, 6404 ret i8 %1405}406 407; FIXME: We should use slli+srai with Zbb for better compression.408define i8 @srai_i8(i8 %a) nounwind {409; RV64I-LABEL: srai_i8:410; RV64I: # %bb.0:411; RV64I-NEXT: slli a0, a0, 56412; RV64I-NEXT: srai a0, a0, 61413; RV64I-NEXT: ret414;415; RV64ZBB-LABEL: srai_i8:416; RV64ZBB: # %bb.0:417; RV64ZBB-NEXT: sext.b a0, a0418; RV64ZBB-NEXT: srai a0, a0, 5419; RV64ZBB-NEXT: ret420;421; RV64ZBKB-LABEL: srai_i8:422; RV64ZBKB: # %bb.0:423; RV64ZBKB-NEXT: slli a0, a0, 56424; RV64ZBKB-NEXT: srai a0, a0, 61425; RV64ZBKB-NEXT: ret426 %1 = ashr i8 %a, 5427 ret i8 %1428}429 430; FIXME: We should use slli+srli.431define i16 @srli_i16(i16 %a) nounwind {432; RV64I-LABEL: srli_i16:433; RV64I: # %bb.0:434; RV64I-NEXT: slli a0, a0, 48435; RV64I-NEXT: srli a0, a0, 48436; RV64I-NEXT: srli a0, a0, 6437; RV64I-NEXT: ret438;439; RV64ZBB-ZBKB-LABEL: srli_i16:440; RV64ZBB-ZBKB: # %bb.0:441; RV64ZBB-ZBKB-NEXT: zext.h a0, a0442; RV64ZBB-ZBKB-NEXT: srli a0, a0, 6443; RV64ZBB-ZBKB-NEXT: ret444 %1 = lshr i16 %a, 6445 ret i16 %1446}447 448; FIXME: We should use slli+srai with Zbb for better compression.449define i16 @srai_i16(i16 %a) nounwind {450; RV64I-LABEL: srai_i16:451; RV64I: # %bb.0:452; RV64I-NEXT: slli a0, a0, 48453; RV64I-NEXT: srai a0, a0, 57454; RV64I-NEXT: ret455;456; RV64ZBB-LABEL: srai_i16:457; RV64ZBB: # %bb.0:458; RV64ZBB-NEXT: sext.h a0, a0459; RV64ZBB-NEXT: srai a0, a0, 9460; RV64ZBB-NEXT: ret461;462; RV64ZBKB-LABEL: srai_i16:463; RV64ZBKB: # %bb.0:464; RV64ZBKB-NEXT: slli a0, a0, 48465; RV64ZBKB-NEXT: srai a0, a0, 57466; RV64ZBKB-NEXT: ret467 %1 = ashr i16 %a, 9468 ret i16 %1469}470