306 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=aarch64 -mattr=+sve < %s | FileCheck %s3 4; This tests that various ands, sexts, and zexts (and other operations)5; operating on vscale or the SVE count instructions can be eliminated6; (via demanded bits) due to their known limited range.7 8; On AArch64 vscale can be at most 16 (for a 2048-bit vector).9; The counting instructions (sans multiplier) have a value of at most 25610; (for a 2048-bit vector of i8s).11 12define i32 @vscale_and_elimination() vscale_range(1,16) {13; CHECK-LABEL: vscale_and_elimination:14; CHECK: // %bb.0:15; CHECK-NEXT: rdvl x8, #116; CHECK-NEXT: lsr x8, x8, #417; CHECK-NEXT: and w9, w8, #0x1c18; CHECK-NEXT: add w0, w8, w919; CHECK-NEXT: ret20 %vscale = call i32 @llvm.vscale.i32()21 %and_redundant = and i32 %vscale, 3122 %and_required = and i32 %vscale, 1717986918023 %result = add i32 %and_redundant, %and_required24 ret i32 %result25}26 27define i64 @cntb_and_elimination() {28; CHECK-LABEL: cntb_and_elimination:29; CHECK: // %bb.0:30; CHECK-NEXT: cntb x831; CHECK-NEXT: and x9, x8, #0x1fc32; CHECK-NEXT: add x0, x8, x933; CHECK-NEXT: ret34 %cntb = call i64 @llvm.aarch64.sve.cntb(i32 31)35 %and_redundant = and i64 %cntb, 51136 %and_required = and i64 %cntb, 1717986918037 %result = add i64 %and_redundant, %and_required38 ret i64 %result39}40 41define i64 @cnth_and_elimination() {42; CHECK-LABEL: cnth_and_elimination:43; CHECK: // %bb.0:44; CHECK-NEXT: cnth x845; CHECK-NEXT: and x9, x8, #0xfc46; CHECK-NEXT: add x0, x8, x947; CHECK-NEXT: ret48 %cnth = call i64 @llvm.aarch64.sve.cnth(i32 31)49 %and_redundant = and i64 %cnth, 102350 %and_required = and i64 %cnth, 1717986918051 %result = add i64 %and_redundant, %and_required52 ret i64 %result53}54 55define i64 @cntw_and_elimination() {56; CHECK-LABEL: cntw_and_elimination:57; CHECK: // %bb.0:58; CHECK-NEXT: cntw x859; CHECK-NEXT: and x9, x8, #0x7c60; CHECK-NEXT: add x0, x8, x961; CHECK-NEXT: ret62 %cntw = call i64 @llvm.aarch64.sve.cntw(i32 31)63 %and_redundant = and i64 %cntw, 12764 %and_required = and i64 %cntw, 1717986918065 %result = add i64 %and_redundant, %and_required66 ret i64 %result67}68 69define i64 @cntd_and_elimination() {70; CHECK-LABEL: cntd_and_elimination:71; CHECK: // %bb.0:72; CHECK-NEXT: cntd x873; CHECK-NEXT: and x9, x8, #0x3c74; CHECK-NEXT: add x0, x8, x975; CHECK-NEXT: ret76 %cntd = call i64 @llvm.aarch64.sve.cntd(i32 31)77 %and_redundant = and i64 %cntd, 6378 %and_required = and i64 %cntd, 1717986918079 %result = add i64 %and_redundant, %and_required80 ret i64 %result81}82 83define i64 @cntp_nxv16i1_and_elimination(<vscale x 16 x i1> %p) {84; CHECK-LABEL: cntp_nxv16i1_and_elimination:85; CHECK: // %bb.0:86; CHECK-NEXT: cntp x8, p0, p0.b87; CHECK-NEXT: and x9, x8, #0x1fc88; CHECK-NEXT: add x0, x8, x989; CHECK-NEXT: ret90 %cntp = tail call i64 @llvm.aarch64.sve.cntp.nxv16i1(<vscale x 16 x i1> %p, <vscale x 16 x i1> %p)91 %and_redundant = and i64 %cntp, 51192 %and_required = and i64 %cntp, 1717986918093 %result = add i64 %and_redundant, %and_required94 ret i64 %result95}96 97define i64 @cntp_nxv8i1_and_elimination(<vscale x 8 x i1> %p) {98; CHECK-LABEL: cntp_nxv8i1_and_elimination:99; CHECK: // %bb.0:100; CHECK-NEXT: cntp x8, p0, p0.h101; CHECK-NEXT: and x9, x8, #0xfc102; CHECK-NEXT: add x0, x8, x9103; CHECK-NEXT: ret104 %cntp = tail call i64 @llvm.aarch64.sve.cntp.nxv8i1(<vscale x 8 x i1> %p, <vscale x 8 x i1> %p)105 %and_redundant = and i64 %cntp, 1023106 %and_required = and i64 %cntp, 17179869180107 %result = add i64 %and_redundant, %and_required108 ret i64 %result109}110 111define i64 @cntp_nxv4i1_and_elimination(<vscale x 4 x i1> %p) {112; CHECK-LABEL: cntp_nxv4i1_and_elimination:113; CHECK: // %bb.0:114; CHECK-NEXT: cntp x8, p0, p0.s115; CHECK-NEXT: and x9, x8, #0x7c116; CHECK-NEXT: add x0, x8, x9117; CHECK-NEXT: ret118 %cntp = tail call i64 @llvm.aarch64.sve.cntp.nxv4i1(<vscale x 4 x i1> %p, <vscale x 4 x i1> %p)119 %and_redundant = and i64 %cntp, 127120 %and_required = and i64 %cntp, 17179869180121 %result = add i64 %and_redundant, %and_required122 ret i64 %result123}124 125define i64 @cntp_nxv2i1_and_elimination(<vscale x 2 x i1> %p) {126; CHECK-LABEL: cntp_nxv2i1_and_elimination:127; CHECK: // %bb.0:128; CHECK-NEXT: cntp x8, p0, p0.d129; CHECK-NEXT: and x9, x8, #0x3c130; CHECK-NEXT: add x0, x8, x9131; CHECK-NEXT: ret132 %cntp = tail call i64 @llvm.aarch64.sve.cntp.nxv2i1(<vscale x 2 x i1> %p, <vscale x 2 x i1> %p)133 %and_redundant = and i64 %cntp, 63134 %and_required = and i64 %cntp, 17179869180135 %result = add i64 %and_redundant, %and_required136 ret i64 %result137}138 139define i64 @vscale_trunc_zext() vscale_range(1,16) {140; CHECK-LABEL: vscale_trunc_zext:141; CHECK: // %bb.0:142; CHECK-NEXT: rdvl x8, #1143; CHECK-NEXT: lsr x0, x8, #4144; CHECK-NEXT: ret145 %vscale = call i32 @llvm.vscale.i32()146 %zext = zext i32 %vscale to i64147 ret i64 %zext148}149 150define i64 @vscale_trunc_sext() vscale_range(1,16) {151; CHECK-LABEL: vscale_trunc_sext:152; CHECK: // %bb.0:153; CHECK-NEXT: rdvl x8, #1154; CHECK-NEXT: lsr x0, x8, #4155; CHECK-NEXT: ret156 %vscale = call i32 @llvm.vscale.i32()157 %sext = sext i32 %vscale to i64158 ret i64 %sext159}160 161define i64 @count_bytes_trunc_zext() {162; CHECK-LABEL: count_bytes_trunc_zext:163; CHECK: // %bb.0:164; CHECK-NEXT: cntb x0165; CHECK-NEXT: ret166 %cnt = call i64 @llvm.aarch64.sve.cntb(i32 31)167 %trunc = trunc i64 %cnt to i32168 %zext = zext i32 %trunc to i64169 ret i64 %zext170}171 172define i64 @count_halfs_trunc_zext() {173; CHECK-LABEL: count_halfs_trunc_zext:174; CHECK: // %bb.0:175; CHECK-NEXT: cnth x0176; CHECK-NEXT: ret177 %cnt = call i64 @llvm.aarch64.sve.cnth(i32 31)178 %trunc = trunc i64 %cnt to i32179 %zext = zext i32 %trunc to i64180 ret i64 %zext181}182 183define i64 @count_words_trunc_zext() {184; CHECK-LABEL: count_words_trunc_zext:185; CHECK: // %bb.0:186; CHECK-NEXT: cntw x0187; CHECK-NEXT: ret188 %cnt = call i64 @llvm.aarch64.sve.cntw(i32 31)189 %trunc = trunc i64 %cnt to i32190 %zext = zext i32 %trunc to i64191 ret i64 %zext192}193 194define i64 @count_doubles_trunc_zext() {195; CHECK-LABEL: count_doubles_trunc_zext:196; CHECK: // %bb.0:197; CHECK-NEXT: cntd x0198; CHECK-NEXT: ret199 %cnt = call i64 @llvm.aarch64.sve.cntd(i32 31)200 %trunc = trunc i64 %cnt to i32201 %zext = zext i32 %trunc to i64202 ret i64 %zext203}204 205define i64 @count_bytes_trunc_sext() {206; CHECK-LABEL: count_bytes_trunc_sext:207; CHECK: // %bb.0:208; CHECK-NEXT: cntb x0209; CHECK-NEXT: ret210 %cnt = call i64 @llvm.aarch64.sve.cntb(i32 31)211 %trunc = trunc i64 %cnt to i32212 %sext = sext i32 %trunc to i64213 ret i64 %sext214}215 216define i64 @count_halfs_trunc_sext() {217; CHECK-LABEL: count_halfs_trunc_sext:218; CHECK: // %bb.0:219; CHECK-NEXT: cnth x0220; CHECK-NEXT: ret221 %cnt = call i64 @llvm.aarch64.sve.cnth(i32 31)222 %trunc = trunc i64 %cnt to i32223 %sext = sext i32 %trunc to i64224 ret i64 %sext225}226 227define i64 @count_words_trunc_sext() {228; CHECK-LABEL: count_words_trunc_sext:229; CHECK: // %bb.0:230; CHECK-NEXT: cntw x0231; CHECK-NEXT: ret232 %cnt = call i64 @llvm.aarch64.sve.cntw(i32 31)233 %trunc = trunc i64 %cnt to i32234 %sext = sext i32 %trunc to i64235 ret i64 %sext236}237 238define i64 @count_doubles_trunc_sext() {239; CHECK-LABEL: count_doubles_trunc_sext:240; CHECK: // %bb.0:241; CHECK-NEXT: cntd x0242; CHECK-NEXT: ret243 %cnt = call i64 @llvm.aarch64.sve.cntd(i32 31)244 %trunc = trunc i64 %cnt to i32245 %sext = sext i32 %trunc to i64246 ret i64 %sext247}248 249define i32 @vscale_with_multiplier() vscale_range(1,16) {250; CHECK-LABEL: vscale_with_multiplier:251; CHECK: // %bb.0:252; CHECK-NEXT: rdvl x8, #1253; CHECK-NEXT: mov w9, #5 // =0x5254; CHECK-NEXT: lsr x8, x8, #4255; CHECK-NEXT: mul x8, x8, x9256; CHECK-NEXT: and w9, w8, #0x3f257; CHECK-NEXT: add w0, w8, w9258; CHECK-NEXT: ret259 %vscale = call i32 @llvm.vscale.i32()260 %mul = mul i32 %vscale, 5261 %and_redundant = and i32 %mul, 127262 %and_required = and i32 %mul, 63263 %result = add i32 %and_redundant, %and_required264 ret i32 %result265}266 267define i32 @vscale_with_negative_multiplier() vscale_range(1,16) {268; CHECK-LABEL: vscale_with_negative_multiplier:269; CHECK: // %bb.0:270; CHECK-NEXT: rdvl x8, #1271; CHECK-NEXT: mov x9, #-5 // =0xfffffffffffffffb272; CHECK-NEXT: lsr x8, x8, #4273; CHECK-NEXT: mul x8, x8, x9274; CHECK-NEXT: and w9, w8, #0xffffffc0275; CHECK-NEXT: add w0, w8, w9276; CHECK-NEXT: ret277 %vscale = call i32 @llvm.vscale.i32()278 %mul = mul i32 %vscale, -5279 %or_redundant = or i32 %mul, 4294967168280 %or_required = and i32 %mul, 4294967232281 %result = add i32 %or_redundant, %or_required282 ret i32 %result283}284 285define i32 @pow2_vscale_with_negative_multiplier() vscale_range(1,16) {286; CHECK-LABEL: pow2_vscale_with_negative_multiplier:287; CHECK: // %bb.0:288; CHECK-NEXT: cntd x8289; CHECK-NEXT: neg x9, x8290; CHECK-NEXT: orr w9, w9, #0xfffffff0291; CHECK-NEXT: sub w0, w9, w8292; CHECK-NEXT: ret293 %vscale = call i32 @llvm.vscale.i32()294 %mul = mul i32 %vscale, -2295 %or_redundant = or i32 %mul, 4294967264296 %or_required = or i32 %mul, 4294967280297 %result = add i32 %or_redundant, %or_required298 ret i32 %result299}300 301declare i32 @llvm.vscale.i32()302declare i64 @llvm.aarch64.sve.cntb(i32 %pattern)303declare i64 @llvm.aarch64.sve.cnth(i32 %pattern)304declare i64 @llvm.aarch64.sve.cntw(i32 %pattern)305declare i64 @llvm.aarch64.sve.cntd(i32 %pattern)306