310 lines · plain
1# RUN: llc -O0 -run-pass=aarch64-prelegalizer-combiner -global-isel %s -o - | FileCheck %s2# RUN: llc -O0 -run-pass=aarch64-prelegalizer-combiner -global-isel %s -o - \3# RUN: -debug-only=aarch64-prelegalizer-combiner,gi-combiner 2>&1 >/dev/null \4# RUN: | FileCheck %s --check-prefix=CHECK-WORKLIST5 6# REQUIRES: asserts7 8--- |9 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"10 target triple = "aarch64--"11 12 define void @multiple_copies(ptr %addr) {13 entry:14 br i1 0, label %if, label %else15 if:16 br label %exit17 else:18 br label %exit19 exit:20 ret void21 }22 23 define void @sink_to_phi_trivially_dominating(ptr %addr) {24 entry:25 br i1 0, label %if, label %exit26 if:27 br label %exit28 exit:29 ret void30 }31 32 define void @sink_to_phi_nondominating(ptr %addr) {33 entry:34 br i1 0, label %if, label %else35 if:36 br label %exit37 else:38 br label %exit39 exit:40 ret void41 }42 43 define void @sink_to_phi_emptyblock(ptr %addr) {44 entry:45 br i1 0, label %if, label %else46 if:47 br label %exit48 else:49 br label %else250 else2:51 br label %exit52 exit:53 ret void54 }55 56 define void @use_doesnt_def_anything(ptr %addr) {57 entry:58 ret void59 }60 61 define void @op0_isnt_a_reg(ptr %addr) {62 entry:63 ret void64 }65...66 67---68name: multiple_copies69# CHECK-LABEL: name: multiple_copies70tracksRegLiveness: true71body: |72 bb.0.entry:73 liveins: $x0, $w174 successors: %bb.1(0x40000000), %bb.2(0x40000000); %bb.1(50.00%), %bb.2(50.00%)75 ; CHECK: [[T0:%[0-9]+]]:_(s32) = G_SEXTLOAD76 %0:_(p0) = COPY $x077 %1:_(s32) = COPY $w178 %2:_(s8) = G_LOAD %0 :: (load (s8) from %ir.addr)79 %3:_(s32) = G_SEXT %280 %4:_(s32) = G_CONSTANT i32 181 %5:_(s1) = G_ICMP intpred(ne), %1:_(s32), %4:_82 G_BRCOND %5:_(s1), %bb.183 G_BR %bb.2.else84 bb.1.if:85 ; CHECK: bb.1.if:86 successors: %bb.3(0x80000000)87 %10:_(s8) = G_CONSTANT i8 188 ; CHECK: [[T1:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)89 %6:_(s8) = G_ADD %2, %1090 ; CHECK: [[T2:%[0-9]+]]:_(s8) = G_ADD [[T1]], {{.*}}91 G_BR %bb.3.exit92 bb.2.else:93 ; CHECK: bb.2.else:94 successors: %bb.3(0x80000000)95 %11:_(s8) = G_CONSTANT i8 196 ; CHECK: [[T3:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)97 %7:_(s8) = G_SUB %2, %1198 ; CHECK: [[T4:%[0-9]+]]:_(s8) = G_ADD [[T3]], {{.*}}99 G_BR %bb.3.exit100 bb.3.exit:101 ; CHECK: bb.3.exit:102 %8:_(s8) = G_PHI %6:_(s8), %bb.1, %7:_(s8), %bb.2103 ; CHECK: [[T5:%[0-9]+]]:_(s8) = G_PHI [[T2]](s8), %bb.1, [[T4]](s8)104 %9:_(s32) = G_ZEXT %8105 ; CHECK: [[T6:%[0-9]+]]:_(s32) = G_ZEXT [[T5]](s8)106 ; CHECK: $w0 = COPY [[T0]](s32)107 ; CHECK: $w1 = COPY [[T6]](s32)108 $w0 = COPY %3109 $w1 = COPY %9110 111# Check that we report the correct modifications to the observer. This acts as112# a test of the debug output and a test.113#114# CHECK-WORKLIST-LABEL: Generic MI Combiner for: multiple_copies115# CHECK-WORKLIST: Try combining [[IN0:%[0-9]+]]:_(s8) = G_LOAD [[IN1:%[0-9]+]]:_(p0){{.*}} :: (load (s8) from %ir.addr)116# CHECK-WORKLIST: Preferred use is: [[IN2:%[0-9]+]]:_(s32) = G_SEXT [[IN0]]:_(s8)117# CHECK-WORKLIST-DAG: Changing: [[IN0]]:_(s8) = G_LOAD [[IN1]]:_(p0){{.*}} :: (load (s8) from %ir.addr)118# CHECK-WORKLIST-DAG: Changing: [[IN3:%[0-9]+]]:_(s8) = G_ADD [[IN0]]:_, [[IN4:%[0-9]+]]:_119# CHECK-WORKLIST-DAG: Changed: [[IN3]]:_(s8) = G_ADD [[NEW1:%[0-9]+]]:_, [[IN4]]:_120# CHECK-WORKLIST-DAG: Changing: [[IN5:%[0-9]+]]:_(s8) = G_SUB [[IN0]]:_, [[IN6:%[0-9]+]]:_121# CHECK-WORKLIST-DAG: Changed: [[IN5]]:_(s8) = G_SUB [[NEW2:%[0-9]+]]:_, [[IN6]]:_122# CHECK-WORKLIST-DAG: Erasing: [[IN2]]:_(s32) = G_SEXT [[IN0]]:_(s8)123# CHECK-WORKLIST-DAG: Changed: [[IN2]]:_(s32) = G_SEXTLOAD [[IN1]]:_(p0){{.*}} :: (load (s8) from %ir.addr)124# CHECK-WORKLIST-DAG: Created: [[NEW1]]:_(s8) = G_TRUNC [[IN2]]:_(s32)125# CHECK-WORKLIST-DAG: Created: [[NEW2]]:_(s8) = G_TRUNC [[IN2]]:_(s32)126# CHECK-WORKLIST: Try combining127...128 129---130name: sink_to_phi_trivially_dominating131# CHECK-LABEL: name: sink_to_phi_trivially_dominating132# This test currently tests that we don't sink if we would sink to a phi. This133# is needed to avoid inserting into the middle of the leading G_PHI instructions134# of a BB135tracksRegLiveness: true136body: |137 bb.0.entry:138 liveins: $x0, $w1139 successors: %bb.1(0x40000000), %bb.2(0x40000000); %bb.1(50.00%), %bb.2(50.00%)140 ; CHECK: [[T0:%[0-9]+]]:_(s32) = G_SEXTLOAD141 %0:_(p0) = COPY $x0142 %1:_(s32) = COPY $w1143 %2:_(s8) = G_LOAD %0 :: (load (s8) from %ir.addr)144 ; CHECK: [[T4:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)145 %3:_(s32) = G_SEXT %2146 %4:_(s32) = G_CONSTANT i32 1147 %5:_(s1) = G_ICMP intpred(ne), %1:_(s32), %4:_148 G_BRCOND %5:_(s1), %bb.1149 G_BR %bb.2.exit150 bb.1.if:151 ; CHECK: bb.1.if:152 successors: %bb.2(0x80000000)153 %10:_(s8) = G_CONSTANT i8 1154 ; CHECK: [[T1:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)155 %6:_(s8) = G_ADD %2, %10156 ; CHECK: [[T2:%[0-9]+]]:_(s8) = G_ADD [[T1]], {{.*}}157 G_BR %bb.2.exit158 bb.2.exit:159 ; CHECK: bb.2.exit:160 %8:_(s8) = G_PHI %6:_(s8), %bb.1, %2:_(s8), %bb.0161 ; CHECK: [[T5:%[0-9]+]]:_(s8) = G_PHI [[T2]](s8), %bb.1, [[T4]](s8)162 %9:_(s32) = G_ZEXT %8163 ; CHECK: [[T6:%[0-9]+]]:_(s32) = G_ZEXT [[T5]](s8)164 ; CHECK: $w0 = COPY [[T0]](s32)165 ; CHECK: $w1 = COPY [[T6]](s32)166 $w0 = COPY %3167 $w1 = COPY %9168...169 170---171name: sink_to_phi_nondominating172# CHECK-LABEL: name: sink_to_phi_nondominating173tracksRegLiveness: true174body: |175 bb.0.entry:176 liveins: $x0, $w1177 successors: %bb.1(0x40000000), %bb.2(0x40000000); %bb.1(50.00%), %bb.2(50.00%)178 ; CHECK: [[T0:%[0-9]+]]:_(s32) = G_SEXTLOAD179 %0:_(p0) = COPY $x0180 %1:_(s32) = COPY $w1181 %2:_(s8) = G_LOAD %0 :: (load (s8) from %ir.addr)182 %3:_(s32) = G_CONSTANT i32 1183 %4:_(s1) = G_ICMP intpred(ne), %1:_(s32), %3:_184 G_BRCOND %4:_(s1), %bb.1185 G_BR %bb.2.else186 bb.1.if:187 ; CHECK: bb.1.if:188 successors: %bb.3(0x80000000)189 %5:_(s8) = G_CONSTANT i8 1190 ; CHECK: [[T1:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)191 %6:_(s8) = G_ADD %2, %5192 ; CHECK: [[T2:%[0-9]+]]:_(s8) = G_ADD [[T1]], {{.*}}193 G_BR %bb.3.exit194 bb.2.else:195 ; CHECK: bb.2.else:196 successors: %bb.3(0x80000000)197 %7:_(s8) = G_CONSTANT i8 1198 ; CHECK: [[T3:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)199 %8:_(s8) = G_SUB %2, %7200 ; CHECK: [[T4:%[0-9]+]]:_(s8) = G_ADD [[T3]], {{.*}}201 G_BR %bb.3.exit202 bb.3.exit:203 ; CHECK: bb.3.exit:204 %9:_(s8) = G_PHI %6:_(s8), %bb.1, %8:_(s8), %bb.2205 ; CHECK: [[T5:%[0-9]+]]:_(s8) = G_PHI [[T2]](s8), %bb.1, [[T4]](s8)206 %10:_(s32) = G_SEXT %2207 %11:_(s32) = G_ZEXT %9208 ; CHECK: [[T6:%[0-9]+]]:_(s32) = G_ZEXT [[T5]](s8)209 ; CHECK: $w0 = COPY [[T0]](s32)210 ; CHECK: $w1 = COPY [[T6]](s32)211 $w0 = COPY %10212 $w1 = COPY %11213# CHECK-WORKLIST-LABEL: Generic MI Combiner for: sink_to_phi_nondominating214# CHECK-WORKLIST: Try combining [[IN0:%[0-9]+]]:_(s8) = G_LOAD [[IN1:%[0-9]+]]:_(p0){{.*}} :: (load (s8) from %ir.addr)215# CHECK-WORKLIST: Preferred use is: [[IN2:%[0-9]+]]:_(s32) = G_SEXT [[IN0]]:_(s8)216# CHECK-WORKLIST-DAG: Changing: [[IN0]]:_(s8) = G_LOAD [[IN1]]:_(p0){{.*}} :: (load (s8) from %ir.addr)217# CHECK-WORKLIST-DAG: Creating: G_TRUNC218# CHECK-WORKLIST-DAG: Changing: [[IN3:%[0-9]+]]:_(s8) = G_ADD [[IN0]]:_, [[IN4:%[0-9]+]]:_219# CHECK-WORKLIST-DAG: Changed: [[IN3]]:_(s8) = G_ADD [[OUT1:%[0-9]+]]:_, [[IN4]]:_220# CHECK-WORKLIST-DAG: Creating: G_TRUNC221# CHECK-WORKLIST-DAG: Changing: [[IN5:%[0-9]+]]:_(s8) = G_SUB [[IN0]]:_, [[IN6:%[0-9]+]]:_222# CHECK-WORKLIST-DAG: Changed: [[IN5]]:_(s8) = G_SUB [[OUT2:%[0-9]+]]:_, [[IN6]]:_223# CHECK-WORKLIST-DAG: Erasing: [[IN2]]:_(s32) = G_SEXT [[IN0]]:_(s8)224# CHECK-WORKLIST-DAG: Changed: [[IN2]]:_(s32) = G_SEXTLOAD [[IN1]]:_(p0){{.*}} :: (load (s8) from %ir.addr)225# CHECK-WORKLIST-DAG: Created: [[OUT1]]:_(s8) = G_TRUNC [[IN2]]:_(s32)226# CHECK-WORKLIST-DAG: Created: [[OUT2]]:_(s8) = G_TRUNC [[IN2]]:_(s32)227# CHECK-WORKLIST: Try combining228...229 230---231name: sink_to_phi_emptyblock232# CHECK-LABEL: name: sink_to_phi_emptyblock233tracksRegLiveness: true234body: |235 bb.0.entry:236 liveins: $x0, $w1237 successors: %bb.1(0x40000000), %bb.2(0x40000000); %bb.1(50.00%), %bb.2(50.00%)238 ; CHECK: [[T0:%[0-9]+]]:_(s32) = G_SEXTLOAD239 %0:_(p0) = COPY $x0240 %1:_(s32) = COPY $w1241 %2:_(s8) = G_LOAD %0 :: (load (s8) from %ir.addr)242 %3:_(s32) = G_SEXT %2243 %4:_(s32) = G_CONSTANT i32 1244 %5:_(s1) = G_ICMP intpred(ne), %1:_(s32), %4:_245 G_BRCOND %5:_(s1), %bb.1246 G_BR %bb.2.else247 bb.1.if:248 ; CHECK: bb.1.if:249 successors: %bb.4(0x80000000)250 %10:_(s8) = G_CONSTANT i8 1251 ; CHECK: [[T1:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)252 %6:_(s8) = G_ADD %2, %10253 ; CHECK: [[T2:%[0-9]+]]:_(s8) = G_ADD [[T1]], {{.*}}254 G_BR %bb.4.exit255 bb.2.else:256 ; CHECK: bb.2.else:257 successors: %bb.3(0x80000000)258 G_BR %bb.3.else2259 bb.3.else2:260 ; CHECK: bb.3.else2:261 successors: %bb.4(0x80000000)262 ; CHECK: [[T4:%[0-9]+]]:_(s8) = G_TRUNC [[T0]](s32)263 ; Fallthrough264 bb.4.exit:265 ; CHECK: bb.4.exit:266 %8:_(s8) = G_PHI %6:_(s8), %bb.1, %2:_(s8), %bb.3267 ; CHECK: [[T5:%[0-9]+]]:_(s8) = G_PHI [[T2]](s8), %bb.1, [[T4]](s8)268 %9:_(s32) = G_ZEXT %8269 ; CHECK: [[T6:%[0-9]+]]:_(s32) = G_ZEXT [[T5]](s8)270 ; CHECK: $w0 = COPY [[T0]](s32)271 ; CHECK: $w1 = COPY [[T6]](s32)272 $w0 = COPY %3273 $w1 = COPY %9274...275 276---277name: use_doesnt_def_anything278# CHECK-LABEL: name: use_doesnt_def_anything279# Check that we don't crash when inspecting a use that doesn't define anything.280# The real issue which was that the combine rule was looking through281# non-truncates as if they were truncates and attempting to obtain the result282# register. It would usually go on to make the right overall decision anyway but283# would sometimes crash on things like (SOME_INTRINSIC imm). This test covers284# the case that it would recover from.285tracksRegLiveness: true286body: |287 bb.0.entry:288 liveins: $x0, $w1289 %0:_(p0) = COPY $x0290 %1:_(s8) = G_LOAD %0 :: (load (s8) from %ir.addr)291 ; CHECK: %1:_(s8) = G_LOAD %0(p0) :: (load (s8) from %ir.addr)292 G_STORE %1(s8), %0(p0) :: (store (s8) into %ir.addr)293 ; CHECK: G_STORE %1(s8), %0(p0) :: (store (s8) into %ir.addr)294...295 296---297name: op0_isnt_a_reg298# CHECK-LABEL: name: op0_isnt_a_reg299# This test covers the variant of use_doesnt_def_anything that would crash.300tracksRegLiveness: true301body: |302 bb.0.entry:303 liveins: $x0, $w1304 %0:_(p0) = COPY $x0305 %1:_(s8) = G_LOAD %0 :: (load (s8) from %ir.addr)306 ; CHECK: %1:_(s8) = G_LOAD %0(p0) :: (load (s8) from %ir.addr)307 G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.hint), %1(s8)308 ; CHECK: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.hint), %1(s8)309...310