368 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=aarch64-none-elf < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD3; RUN: llc -mtriple=aarch64-none-elf -global-isel < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI4 5@var1_32 = global i32 06@var2_32 = global i32 07 8@var1_64 = global i64 09@var2_64 = global i64 010 11define void @logical_32bit() minsize {12; CHECK-LABEL: logical_32bit:13; CHECK: // %bb.0:14; CHECK-NEXT: adrp x8, :got:var1_3215; CHECK-NEXT: adrp x9, :got:var2_3216; CHECK-NEXT: ldr x8, [x8, :got_lo12:var1_32]17; CHECK-NEXT: ldr x9, [x9, :got_lo12:var2_32]18; CHECK-NEXT: ldr w10, [x8]19; CHECK-NEXT: ldr w9, [x9]20; CHECK-NEXT: and w11, w10, w921; CHECK-NEXT: bic w12, w10, w922; CHECK-NEXT: str w11, [x8]23; CHECK-NEXT: orr w11, w10, w924; CHECK-NEXT: str w12, [x8]25; CHECK-NEXT: orn w12, w10, w926; CHECK-NEXT: str w11, [x8]27; CHECK-NEXT: eor w11, w10, w928; CHECK-NEXT: str w12, [x8]29; CHECK-NEXT: eon w12, w9, w1030; CHECK-NEXT: str w11, [x8]31; CHECK-NEXT: and w11, w10, w9, lsl #3132; CHECK-NEXT: str w12, [x8]33; CHECK-NEXT: bic w12, w10, w9, lsl #3134; CHECK-NEXT: str w11, [x8]35; CHECK-NEXT: orr w11, w10, w9, lsl #3136; CHECK-NEXT: str w12, [x8]37; CHECK-NEXT: orn w12, w10, w9, lsl #3138; CHECK-NEXT: str w11, [x8]39; CHECK-NEXT: eor w11, w10, w9, lsl #3140; CHECK-NEXT: str w12, [x8]41; CHECK-NEXT: eon w12, w10, w9, lsl #3142; CHECK-NEXT: str w11, [x8]43; CHECK-NEXT: bic w11, w10, w9, asr #1044; CHECK-NEXT: str w12, [x8]45; CHECK-NEXT: eor w12, w10, w9, asr #1046; CHECK-NEXT: str w11, [x8]47; CHECK-NEXT: orn w11, w10, w9, lsr #148; CHECK-NEXT: str w12, [x8]49; CHECK-NEXT: eor w12, w10, w9, lsr #150; CHECK-NEXT: str w11, [x8]51; CHECK-NEXT: eon w11, w10, w9, ror #2052; CHECK-NEXT: and w9, w10, w9, ror #2053; CHECK-NEXT: str w12, [x8]54; CHECK-NEXT: str w11, [x8]55; CHECK-NEXT: str w9, [x8]56; CHECK-NEXT: ret57 %val1 = load i32, ptr @var1_3258 %val2 = load i32, ptr @var2_3259 60 ; First check basic and/bic/or/orn/eor/eon patterns with no shift61 %neg_val2 = xor i32 -1, %val262 63 %and_noshift = and i32 %val1, %val264 store volatile i32 %and_noshift, ptr @var1_3265 %bic_noshift = and i32 %neg_val2, %val166 store volatile i32 %bic_noshift, ptr @var1_3267 68 %or_noshift = or i32 %val1, %val269 store volatile i32 %or_noshift, ptr @var1_3270 %orn_noshift = or i32 %neg_val2, %val171 store volatile i32 %orn_noshift, ptr @var1_3272 73 %xor_noshift = xor i32 %val1, %val274 store volatile i32 %xor_noshift, ptr @var1_3275 %xorn_noshift = xor i32 %neg_val2, %val176 store volatile i32 %xorn_noshift, ptr @var1_3277 78 ; Check the maximum shift on each79 %operand_lsl31 = shl i32 %val2, 3180 %neg_operand_lsl31 = xor i32 -1, %operand_lsl3181 82 %and_lsl31 = and i32 %val1, %operand_lsl3183 store volatile i32 %and_lsl31, ptr @var1_3284 %bic_lsl31 = and i32 %val1, %neg_operand_lsl3185 store volatile i32 %bic_lsl31, ptr @var1_3286 87 %or_lsl31 = or i32 %val1, %operand_lsl3188 store volatile i32 %or_lsl31, ptr @var1_3289 %orn_lsl31 = or i32 %val1, %neg_operand_lsl3190 store volatile i32 %orn_lsl31, ptr @var1_3291 92 %xor_lsl31 = xor i32 %val1, %operand_lsl3193 store volatile i32 %xor_lsl31, ptr @var1_3294 %xorn_lsl31 = xor i32 %val1, %neg_operand_lsl3195 store volatile i32 %xorn_lsl31, ptr @var1_3296 97 ; Check other shifts on a subset98 %operand_asr10 = ashr i32 %val2, 1099 %neg_operand_asr10 = xor i32 -1, %operand_asr10100 101 %bic_asr10 = and i32 %val1, %neg_operand_asr10102 store volatile i32 %bic_asr10, ptr @var1_32103 %xor_asr10 = xor i32 %val1, %operand_asr10104 store volatile i32 %xor_asr10, ptr @var1_32105 106 %operand_lsr1 = lshr i32 %val2, 1107 %neg_operand_lsr1 = xor i32 -1, %operand_lsr1108 109 %orn_lsr1 = or i32 %val1, %neg_operand_lsr1110 store volatile i32 %orn_lsr1, ptr @var1_32111 %xor_lsr1 = xor i32 %val1, %operand_lsr1112 store volatile i32 %xor_lsr1, ptr @var1_32113 114 %operand_ror20_big = shl i32 %val2, 12115 %operand_ror20_small = lshr i32 %val2, 20116 %operand_ror20 = or i32 %operand_ror20_big, %operand_ror20_small117 %neg_operand_ror20 = xor i32 -1, %operand_ror20118 119 %xorn_ror20 = xor i32 %val1, %neg_operand_ror20120 store volatile i32 %xorn_ror20, ptr @var1_32121 %and_ror20 = and i32 %val1, %operand_ror20122 store volatile i32 %and_ror20, ptr @var1_32123 124 ret void125}126 127define void @logical_64bit() minsize {128; CHECK-LABEL: logical_64bit:129; CHECK: // %bb.0:130; CHECK-NEXT: adrp x8, :got:var1_64131; CHECK-NEXT: adrp x9, :got:var2_64132; CHECK-NEXT: ldr x8, [x8, :got_lo12:var1_64]133; CHECK-NEXT: ldr x9, [x9, :got_lo12:var2_64]134; CHECK-NEXT: ldr x10, [x8]135; CHECK-NEXT: ldr x9, [x9]136; CHECK-NEXT: and x11, x10, x9137; CHECK-NEXT: bic x12, x10, x9138; CHECK-NEXT: str x11, [x8]139; CHECK-NEXT: orr x11, x10, x9140; CHECK-NEXT: str x12, [x8]141; CHECK-NEXT: orn x12, x10, x9142; CHECK-NEXT: str x11, [x8]143; CHECK-NEXT: eor x11, x10, x9144; CHECK-NEXT: str x12, [x8]145; CHECK-NEXT: eon x12, x9, x10146; CHECK-NEXT: str x11, [x8]147; CHECK-NEXT: and x11, x10, x9, lsl #63148; CHECK-NEXT: str x12, [x8]149; CHECK-NEXT: bic x12, x10, x9, lsl #63150; CHECK-NEXT: str x11, [x8]151; CHECK-NEXT: orr x11, x10, x9, lsl #63152; CHECK-NEXT: str x12, [x8]153; CHECK-NEXT: orn x12, x10, x9, lsl #63154; CHECK-NEXT: str x11, [x8]155; CHECK-NEXT: eor x11, x10, x9, lsl #63156; CHECK-NEXT: str x12, [x8]157; CHECK-NEXT: eon x12, x10, x9, lsl #63158; CHECK-NEXT: str x11, [x8]159; CHECK-NEXT: bic x11, x10, x9, asr #10160; CHECK-NEXT: str x12, [x8]161; CHECK-NEXT: eor x12, x10, x9, asr #10162; CHECK-NEXT: str x11, [x8]163; CHECK-NEXT: orn x11, x10, x9, lsr #1164; CHECK-NEXT: str x12, [x8]165; CHECK-NEXT: eor x12, x10, x9, lsr #1166; CHECK-NEXT: str x11, [x8]167; CHECK-NEXT: eon x11, x10, x9, ror #20168; CHECK-NEXT: and x9, x10, x9, ror #20169; CHECK-NEXT: str x12, [x8]170; CHECK-NEXT: str x11, [x8]171; CHECK-NEXT: str x9, [x8]172; CHECK-NEXT: ret173 %val1 = load i64, ptr @var1_64174 %val2 = load i64, ptr @var2_64175 176 ; First check basic and/bic/or/orn/eor/eon patterns with no shift177 %neg_val2 = xor i64 -1, %val2178 179 %and_noshift = and i64 %val1, %val2180 store volatile i64 %and_noshift, ptr @var1_64181 %bic_noshift = and i64 %neg_val2, %val1182 store volatile i64 %bic_noshift, ptr @var1_64183 184 %or_noshift = or i64 %val1, %val2185 store volatile i64 %or_noshift, ptr @var1_64186 %orn_noshift = or i64 %neg_val2, %val1187 store volatile i64 %orn_noshift, ptr @var1_64188 189 %xor_noshift = xor i64 %val1, %val2190 store volatile i64 %xor_noshift, ptr @var1_64191 %xorn_noshift = xor i64 %neg_val2, %val1192 store volatile i64 %xorn_noshift, ptr @var1_64193 194 ; Check the maximum shift on each195 %operand_lsl63 = shl i64 %val2, 63196 %neg_operand_lsl63 = xor i64 -1, %operand_lsl63197 198 %and_lsl63 = and i64 %val1, %operand_lsl63199 store volatile i64 %and_lsl63, ptr @var1_64200 %bic_lsl63 = and i64 %val1, %neg_operand_lsl63201 store volatile i64 %bic_lsl63, ptr @var1_64202 203 %or_lsl63 = or i64 %val1, %operand_lsl63204 store volatile i64 %or_lsl63, ptr @var1_64205 %orn_lsl63 = or i64 %val1, %neg_operand_lsl63206 store volatile i64 %orn_lsl63, ptr @var1_64207 208 %xor_lsl63 = xor i64 %val1, %operand_lsl63209 store volatile i64 %xor_lsl63, ptr @var1_64210 %xorn_lsl63 = xor i64 %val1, %neg_operand_lsl63211 store volatile i64 %xorn_lsl63, ptr @var1_64212 213 ; Check other shifts on a subset214 %operand_asr10 = ashr i64 %val2, 10215 %neg_operand_asr10 = xor i64 -1, %operand_asr10216 217 %bic_asr10 = and i64 %val1, %neg_operand_asr10218 store volatile i64 %bic_asr10, ptr @var1_64219 %xor_asr10 = xor i64 %val1, %operand_asr10220 store volatile i64 %xor_asr10, ptr @var1_64221 222 %operand_lsr1 = lshr i64 %val2, 1223 %neg_operand_lsr1 = xor i64 -1, %operand_lsr1224 225 %orn_lsr1 = or i64 %val1, %neg_operand_lsr1226 store volatile i64 %orn_lsr1, ptr @var1_64227 %xor_lsr1 = xor i64 %val1, %operand_lsr1228 store volatile i64 %xor_lsr1, ptr @var1_64229 230 ; Construct a rotate-right from a bunch of other logical231 ; operations. DAGCombiner should ensure we the ROTR during232 ; selection233 %operand_ror20_big = shl i64 %val2, 44234 %operand_ror20_small = lshr i64 %val2, 20235 %operand_ror20 = or i64 %operand_ror20_big, %operand_ror20_small236 %neg_operand_ror20 = xor i64 -1, %operand_ror20237 238 %xorn_ror20 = xor i64 %val1, %neg_operand_ror20239 store volatile i64 %xorn_ror20, ptr @var1_64240 %and_ror20 = and i64 %val1, %operand_ror20241 store volatile i64 %and_ror20, ptr @var1_64242 243 ret void244}245 246define void @flag_setting() {247; CHECK-SD-LABEL: flag_setting:248; CHECK-SD: // %bb.0:249; CHECK-SD-NEXT: adrp x8, :got:var1_64250; CHECK-SD-NEXT: adrp x10, :got:var2_64251; CHECK-SD-NEXT: ldr x8, [x8, :got_lo12:var1_64]252; CHECK-SD-NEXT: ldr x10, [x10, :got_lo12:var2_64]253; CHECK-SD-NEXT: ldr x9, [x8]254; CHECK-SD-NEXT: ldr x10, [x10]255; CHECK-SD-NEXT: tst x9, x10256; CHECK-SD-NEXT: b.gt .LBB2_4257; CHECK-SD-NEXT: // %bb.1: // %test2258; CHECK-SD-NEXT: tst x9, x10, lsl #63259; CHECK-SD-NEXT: b.mi .LBB2_4260; CHECK-SD-NEXT: // %bb.2: // %test3261; CHECK-SD-NEXT: tst x9, x10, asr #12262; CHECK-SD-NEXT: b.gt .LBB2_4263; CHECK-SD-NEXT: // %bb.3: // %other_exit264; CHECK-SD-NEXT: str x9, [x8]265; CHECK-SD-NEXT: .LBB2_4: // %common.ret266; CHECK-SD-NEXT: ret267;268; CHECK-GI-LABEL: flag_setting:269; CHECK-GI: // %bb.0:270; CHECK-GI-NEXT: adrp x8, :got:var1_64271; CHECK-GI-NEXT: adrp x10, :got:var2_64272; CHECK-GI-NEXT: ldr x8, [x8, :got_lo12:var1_64]273; CHECK-GI-NEXT: ldr x10, [x10, :got_lo12:var2_64]274; CHECK-GI-NEXT: ldr x9, [x8]275; CHECK-GI-NEXT: ldr x10, [x10]276; CHECK-GI-NEXT: tst x9, x10277; CHECK-GI-NEXT: b.gt .LBB2_4278; CHECK-GI-NEXT: // %bb.1: // %test2279; CHECK-GI-NEXT: tst x9, x10, lsl #63280; CHECK-GI-NEXT: b.mi .LBB2_4281; CHECK-GI-NEXT: // %bb.2: // %test3282; CHECK-GI-NEXT: asr x10, x10, #12283; CHECK-GI-NEXT: tst x10, x9284; CHECK-GI-NEXT: b.gt .LBB2_4285; CHECK-GI-NEXT: // %bb.3: // %other_exit286; CHECK-GI-NEXT: str x9, [x8]287; CHECK-GI-NEXT: .LBB2_4: // %common.ret288; CHECK-GI-NEXT: ret289 %val1 = load i64, ptr @var1_64290 %val2 = load i64, ptr @var2_64291 292 %simple_and = and i64 %val1, %val2293 %tst1 = icmp sgt i64 %simple_and, 0294 br i1 %tst1, label %ret, label %test2, !prof !1295 296test2:297 %shifted_op = shl i64 %val2, 63298 %shifted_and = and i64 %val1, %shifted_op299 %tst2 = icmp slt i64 %shifted_and, 0300 br i1 %tst2, label %ret, label %test3, !prof !1301 302test3:303 %asr_op = ashr i64 %val2, 12304 %asr_and = and i64 %asr_op, %val1305 %tst3 = icmp sgt i64 %asr_and, 0306 br i1 %tst3, label %ret, label %other_exit, !prof !1307 308other_exit:309 store volatile i64 %val1, ptr @var1_64310 ret void311ret:312 ret void313}314 315define i64 @add_swap_rhs_lhs_i64(i64 %0, i64 %1) {316; CHECK-LABEL: add_swap_rhs_lhs_i64:317; CHECK: // %bb.0:318; CHECK-NEXT: lsl x8, x0, #8319; CHECK-NEXT: add x0, x8, x1, lsl #3320; CHECK-NEXT: ret321 %3 = shl i64 %0, 8322 %4 = shl i64 %1, 3323 %5 = add i64 %4, %3324 ret i64 %5325}326 327define i64 @add_swap_no_op_i64(i64 %0, i64 %1, ptr %2) {328; CHECK-LABEL: add_swap_no_op_i64:329; CHECK: // %bb.0:330; CHECK-NEXT: lsl x8, x1, #3331; CHECK-NEXT: add x0, x8, x0, lsl #8332; CHECK-NEXT: str x8, [x2]333; CHECK-NEXT: ret334 %4 = shl i64 %0, 8335 %5 = shl i64 %1, 3336 store i64 %5, ptr %2337 %6 = add i64 %5, %4338 ret i64 %6339}340 341define i32 @add_swap_rhs_lhs_i32(i32 %0, i32 %1) {342; CHECK-LABEL: add_swap_rhs_lhs_i32:343; CHECK: // %bb.0:344; CHECK-NEXT: lsl w8, w0, #8345; CHECK-NEXT: add w0, w8, w1, lsl #3346; CHECK-NEXT: ret347 %3 = shl i32 %0, 8348 %4 = shl i32 %1, 3349 %5 = add i32 %4, %3350 ret i32 %5351}352 353define i32 @add_swap_no_op_i32(i32 %0, i32 %1, ptr %2) {354; CHECK-LABEL: add_swap_no_op_i32:355; CHECK: // %bb.0:356; CHECK-NEXT: lsl w8, w1, #3357; CHECK-NEXT: add w0, w8, w0, lsl #8358; CHECK-NEXT: str w8, [x2]359; CHECK-NEXT: ret360 %4 = shl i32 %0, 8361 %5 = shl i32 %1, 3362 store i32 %5, ptr %2363 %6 = add i32 %5, %4364 ret i32 %6365}366 367!1 = !{!"branch_weights", i32 1, i32 1}368