578 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=avr -mattr=movw -verify-machineinstrs | FileCheck %s3 4define i32 @shl_i32_1(i32 %a) {5; CHECK-LABEL: shl_i32_1:6; CHECK: ; %bb.0:7; CHECK-NEXT: lsl r228; CHECK-NEXT: rol r239; CHECK-NEXT: rol r2410; CHECK-NEXT: rol r2511; CHECK-NEXT: ret12 %res = shl i32 %a, 113 ret i32 %res14}15 16define i32 @shl_i32_2(i32 %a) {17; CHECK-LABEL: shl_i32_2:18; CHECK: ; %bb.0:19; CHECK-NEXT: lsl r2220; CHECK-NEXT: rol r2321; CHECK-NEXT: rol r2422; CHECK-NEXT: rol r2523; CHECK-NEXT: lsl r2224; CHECK-NEXT: rol r2325; CHECK-NEXT: rol r2426; CHECK-NEXT: rol r2527; CHECK-NEXT: ret28 %res = shl i32 %a, 229 ret i32 %res30}31 32define i32 @shl_i32_4(i32 %a) {33; CHECK-LABEL: shl_i32_4:34; CHECK: ; %bb.0:35; CHECK-NEXT: swap r2536; CHECK-NEXT: andi r25, 24037; CHECK-NEXT: swap r2438; CHECK-NEXT: eor r25, r2439; CHECK-NEXT: andi r24, 24040; CHECK-NEXT: eor r25, r2441; CHECK-NEXT: swap r2342; CHECK-NEXT: eor r24, r2343; CHECK-NEXT: andi r23, 24044; CHECK-NEXT: eor r24, r2345; CHECK-NEXT: swap r2246; CHECK-NEXT: eor r23, r2247; CHECK-NEXT: andi r22, 24048; CHECK-NEXT: eor r23, r2249; CHECK-NEXT: ret50 %res = shl i32 %a, 451 ret i32 %res52}53 54; shift four bits and then shift one bit55define i32 @shl_i32_5(i32 %a) {56; CHECK-LABEL: shl_i32_5:57; CHECK: ; %bb.0:58; CHECK-NEXT: swap r2559; CHECK-NEXT: andi r25, 24060; CHECK-NEXT: swap r2461; CHECK-NEXT: eor r25, r2462; CHECK-NEXT: andi r24, 24063; CHECK-NEXT: eor r25, r2464; CHECK-NEXT: swap r2365; CHECK-NEXT: eor r24, r2366; CHECK-NEXT: andi r23, 24067; CHECK-NEXT: eor r24, r2368; CHECK-NEXT: swap r2269; CHECK-NEXT: eor r23, r2270; CHECK-NEXT: andi r22, 24071; CHECK-NEXT: eor r23, r2272; CHECK-NEXT: lsl r2273; CHECK-NEXT: rol r2374; CHECK-NEXT: rol r2475; CHECK-NEXT: rol r2576; CHECK-NEXT: ret77 %res = shl i32 %a, 578 ret i32 %res79}80 81; shift two to the right and move the registers around82define i32 @shl_i32_6(i32 %a) {83; CHECK-LABEL: shl_i32_6:84; CHECK: ; %bb.0:85; CHECK-NEXT: lsr r2586; CHECK-NEXT: ror r2487; CHECK-NEXT: ror r2388; CHECK-NEXT: ror r2289; CHECK-NEXT: mov r18, r190; CHECK-NEXT: ror r1891; CHECK-NEXT: lsr r2592; CHECK-NEXT: ror r2493; CHECK-NEXT: ror r2394; CHECK-NEXT: ror r2295; CHECK-NEXT: ror r1896; CHECK-NEXT: mov r25, r2497; CHECK-NEXT: mov r24, r2398; CHECK-NEXT: mov r19, r2299; CHECK-NEXT: movw r22, r18100; CHECK-NEXT: ret101 %res = shl i32 %a, 6102 ret i32 %res103}104 105 106; shift one to the right and move registers around107define i32 @shl_i32_7(i32 %a) {108; CHECK-LABEL: shl_i32_7:109; CHECK: ; %bb.0:110; CHECK-NEXT: lsr r25111; CHECK-NEXT: ror r24112; CHECK-NEXT: ror r23113; CHECK-NEXT: ror r22114; CHECK-NEXT: mov r18, r1115; CHECK-NEXT: ror r18116; CHECK-NEXT: mov r25, r24117; CHECK-NEXT: mov r24, r23118; CHECK-NEXT: mov r19, r22119; CHECK-NEXT: movw r22, r18120; CHECK-NEXT: ret121 %res = shl i32 %a, 7122 ret i32 %res123}124 125define i32 @shl_i32_8(i32 %a) {126; CHECK-LABEL: shl_i32_8:127; CHECK: ; %bb.0:128; CHECK-NEXT: mov r25, r24129; CHECK-NEXT: mov r24, r23130; CHECK-NEXT: mov r23, r22131; CHECK-NEXT: mov r22, r1132; CHECK-NEXT: ret133 %res = shl i32 %a, 8134 ret i32 %res135}136 137define i32 @shl_i32_9(i32 %a) {138; CHECK-LABEL: shl_i32_9:139; CHECK: ; %bb.0:140; CHECK-NEXT: lsl r22141; CHECK-NEXT: rol r23142; CHECK-NEXT: rol r24143; CHECK-NEXT: mov r25, r24144; CHECK-NEXT: mov r24, r23145; CHECK-NEXT: mov r23, r22146; CHECK-NEXT: mov r22, r1147; CHECK-NEXT: ret148 %res = shl i32 %a, 9149 ret i32 %res150}151 152; shift 3 of 4 registers and move the others around153define i32 @shl_i32_12(i32 %a) {154; CHECK-LABEL: shl_i32_12:155; CHECK: ; %bb.0:156; CHECK-NEXT: swap r24157; CHECK-NEXT: andi r24, 240158; CHECK-NEXT: swap r23159; CHECK-NEXT: eor r24, r23160; CHECK-NEXT: andi r23, 240161; CHECK-NEXT: eor r24, r23162; CHECK-NEXT: swap r22163; CHECK-NEXT: eor r23, r22164; CHECK-NEXT: andi r22, 240165; CHECK-NEXT: eor r23, r22166; CHECK-NEXT: mov r25, r24167; CHECK-NEXT: mov r24, r23168; CHECK-NEXT: mov r23, r22169; CHECK-NEXT: mov r22, r1170; CHECK-NEXT: ret171 %res = shl i32 %a, 12172 ret i32 %res173}174 175define i32 @shl_i32_15(i32 %a) {176; CHECK-LABEL: shl_i32_15:177; CHECK: ; %bb.0:178; CHECK-NEXT: movw r18, r22179; CHECK-NEXT: lsr r24180; CHECK-NEXT: ror r19181; CHECK-NEXT: ror r18182; CHECK-NEXT: mov r23, r1183; CHECK-NEXT: ror r23184; CHECK-NEXT: mov r22, r1185; CHECK-NEXT: movw r24, r18186; CHECK-NEXT: ret187 %res = shl i32 %a, 15188 ret i32 %res189}190 191; This is a special case: this shift is performed directly inside SelectionDAG192; instead of as a custom lowering like the other shift operations.193define i32 @shl_i32_16(i32 %a) {194; CHECK-LABEL: shl_i32_16:195; CHECK: ; %bb.0:196; CHECK-NEXT: movw r24, r22197; CHECK-NEXT: ldi r22, 0198; CHECK-NEXT: ldi r23, 0199; CHECK-NEXT: ret200 %res = shl i32 %a, 16201 ret i32 %res202}203 204; Combined with the register allocator, shift instructions can sometimes be205; optimized away entirely. The least significant registers are simply stored206; directly instead of moving them first.207define void @shl_i32_16_ptr(i32 %a, ptr %ptr) {208; CHECK-LABEL: shl_i32_16_ptr:209; CHECK: ; %bb.0:210; CHECK-NEXT: movw r30, r20211; CHECK-NEXT: std Z+3, r23212; CHECK-NEXT: std Z+2, r22213; CHECK-NEXT: ldi r24, 0214; CHECK-NEXT: ldi r25, 0215; CHECK-NEXT: std Z+1, r25216; CHECK-NEXT: st Z, r24217; CHECK-NEXT: ret218 %res = shl i32 %a, 16219 store i32 %res, ptr %ptr220 ret void221}222 223; shift only the most significant byte and then move it224define i32 @shl_i32_28(i32 %a) {225; CHECK-LABEL: shl_i32_28:226; CHECK: ; %bb.0:227; CHECK-NEXT: swap r22228; CHECK-NEXT: andi r22, 240229; CHECK-NEXT: mov r25, r22230; CHECK-NEXT: mov r24, r1231; CHECK-NEXT: mov r23, r1232; CHECK-NEXT: mov r22, r1233; CHECK-NEXT: ret234 %res = shl i32 %a, 28235 ret i32 %res236}237 238; move the rightmost bit to the leftmost bit and clear the rest239define i32 @shl_i32_31(i32 %a) {240; CHECK-LABEL: shl_i32_31:241; CHECK: ; %bb.0:242; CHECK-NEXT: lsr r22243; CHECK-NEXT: mov r25, r1244; CHECK-NEXT: ror r25245; CHECK-NEXT: mov r24, r1246; CHECK-NEXT: mov r23, r1247; CHECK-NEXT: mov r22, r1248; CHECK-NEXT: ret249 %res = shl i32 %a, 31250 ret i32 %res251}252 253define i32 @lshr_i32_1(i32 %a) {254; CHECK-LABEL: lshr_i32_1:255; CHECK: ; %bb.0:256; CHECK-NEXT: lsr r25257; CHECK-NEXT: ror r24258; CHECK-NEXT: ror r23259; CHECK-NEXT: ror r22260; CHECK-NEXT: ret261 %res = lshr i32 %a, 1262 ret i32 %res263}264 265define i32 @lshr_i32_2(i32 %a) {266; CHECK-LABEL: lshr_i32_2:267; CHECK: ; %bb.0:268; CHECK-NEXT: lsr r25269; CHECK-NEXT: ror r24270; CHECK-NEXT: ror r23271; CHECK-NEXT: ror r22272; CHECK-NEXT: lsr r25273; CHECK-NEXT: ror r24274; CHECK-NEXT: ror r23275; CHECK-NEXT: ror r22276; CHECK-NEXT: ret277 %res = lshr i32 %a, 2278 ret i32 %res279}280 281define i32 @lshr_i32_4(i32 %a) {282; CHECK-LABEL: lshr_i32_4:283; CHECK: ; %bb.0:284; CHECK-NEXT: swap r22285; CHECK-NEXT: andi r22, 15286; CHECK-NEXT: swap r23287; CHECK-NEXT: eor r22, r23288; CHECK-NEXT: andi r23, 15289; CHECK-NEXT: eor r22, r23290; CHECK-NEXT: swap r24291; CHECK-NEXT: eor r23, r24292; CHECK-NEXT: andi r24, 15293; CHECK-NEXT: eor r23, r24294; CHECK-NEXT: swap r25295; CHECK-NEXT: eor r24, r25296; CHECK-NEXT: andi r25, 15297; CHECK-NEXT: eor r24, r25298; CHECK-NEXT: ret299 %res = lshr i32 %a, 4300 ret i32 %res301}302 303define i32 @lshr_i32_6(i32 %a) {304; CHECK-LABEL: lshr_i32_6:305; CHECK: ; %bb.0:306; CHECK-NEXT: lsl r22307; CHECK-NEXT: rol r23308; CHECK-NEXT: rol r24309; CHECK-NEXT: rol r25310; CHECK-NEXT: mov r19, r1311; CHECK-NEXT: rol r19312; CHECK-NEXT: lsl r22313; CHECK-NEXT: rol r23314; CHECK-NEXT: rol r24315; CHECK-NEXT: rol r25316; CHECK-NEXT: rol r19317; CHECK-NEXT: mov r22, r23318; CHECK-NEXT: mov r23, r24319; CHECK-NEXT: mov r18, r25320; CHECK-NEXT: movw r24, r18321; CHECK-NEXT: ret322 %res = lshr i32 %a, 6323 ret i32 %res324}325 326define i32 @lshr_i32_7(i32 %a) {327; CHECK-LABEL: lshr_i32_7:328; CHECK: ; %bb.0:329; CHECK-NEXT: lsl r22330; CHECK-NEXT: rol r23331; CHECK-NEXT: rol r24332; CHECK-NEXT: rol r25333; CHECK-NEXT: mov r19, r1334; CHECK-NEXT: rol r19335; CHECK-NEXT: mov r22, r23336; CHECK-NEXT: mov r23, r24337; CHECK-NEXT: mov r18, r25338; CHECK-NEXT: movw r24, r18339; CHECK-NEXT: ret340 %res = lshr i32 %a, 7341 ret i32 %res342}343 344define i32 @lshr_i32_8(i32 %a) {345; CHECK-LABEL: lshr_i32_8:346; CHECK: ; %bb.0:347; CHECK-NEXT: mov r22, r23348; CHECK-NEXT: mov r23, r24349; CHECK-NEXT: mov r24, r25350; CHECK-NEXT: mov r25, r1351; CHECK-NEXT: ret352 %res = lshr i32 %a, 8353 ret i32 %res354}355 356define i32 @lshr_i32_9(i32 %a) {357; CHECK-LABEL: lshr_i32_9:358; CHECK: ; %bb.0:359; CHECK-NEXT: lsr r25360; CHECK-NEXT: ror r24361; CHECK-NEXT: ror r23362; CHECK-NEXT: mov r22, r23363; CHECK-NEXT: mov r23, r24364; CHECK-NEXT: mov r24, r25365; CHECK-NEXT: mov r25, r1366; CHECK-NEXT: ret367 %res = lshr i32 %a, 9368 ret i32 %res369}370 371define i32 @lshr_i32_16(i32 %a) {372; CHECK-LABEL: lshr_i32_16:373; CHECK: ; %bb.0:374; CHECK-NEXT: movw r22, r24375; CHECK-NEXT: ldi r24, 0376; CHECK-NEXT: ldi r25, 0377; CHECK-NEXT: ret378 %res = lshr i32 %a, 16379 ret i32 %res380}381 382define i32 @lshr_i32_24(i32 %a) {383; CHECK-LABEL: lshr_i32_24:384; CHECK: ; %bb.0:385; CHECK-NEXT: mov r22, r25386; CHECK-NEXT: mov r23, r1387; CHECK-NEXT: mov r24, r1388; CHECK-NEXT: mov r25, r1389; CHECK-NEXT: ret390 %res = lshr i32 %a, 24391 ret i32 %res392}393 394define i32 @lshr_i32_31(i32 %a) {395; CHECK-LABEL: lshr_i32_31:396; CHECK: ; %bb.0:397; CHECK-NEXT: lsl r25398; CHECK-NEXT: mov r22, r1399; CHECK-NEXT: rol r22400; CHECK-NEXT: mov r23, r1401; CHECK-NEXT: mov r24, r1402; CHECK-NEXT: mov r25, r1403; CHECK-NEXT: ret404 %res = lshr i32 %a, 31405 ret i32 %res406}407 408define i32 @ashr_i32_1(i32 %a) {409; CHECK-LABEL: ashr_i32_1:410; CHECK: ; %bb.0:411; CHECK-NEXT: asr r25412; CHECK-NEXT: ror r24413; CHECK-NEXT: ror r23414; CHECK-NEXT: ror r22415; CHECK-NEXT: ret416 %res = ashr i32 %a, 1417 ret i32 %res418}419 420define i32 @ashr_i32_2(i32 %a) {421; CHECK-LABEL: ashr_i32_2:422; CHECK: ; %bb.0:423; CHECK-NEXT: asr r25424; CHECK-NEXT: ror r24425; CHECK-NEXT: ror r23426; CHECK-NEXT: ror r22427; CHECK-NEXT: asr r25428; CHECK-NEXT: ror r24429; CHECK-NEXT: ror r23430; CHECK-NEXT: ror r22431; CHECK-NEXT: ret432 %res = ashr i32 %a, 2433 ret i32 %res434}435 436; can't use the swap/andi/eor trick here437define i32 @ashr_i32_4(i32 %a) {438; CHECK-LABEL: ashr_i32_4:439; CHECK: ; %bb.0:440; CHECK-NEXT: asr r25441; CHECK-NEXT: ror r24442; CHECK-NEXT: ror r23443; CHECK-NEXT: ror r22444; CHECK-NEXT: asr r25445; CHECK-NEXT: ror r24446; CHECK-NEXT: ror r23447; CHECK-NEXT: ror r22448; CHECK-NEXT: asr r25449; CHECK-NEXT: ror r24450; CHECK-NEXT: ror r23451; CHECK-NEXT: ror r22452; CHECK-NEXT: asr r25453; CHECK-NEXT: ror r24454; CHECK-NEXT: ror r23455; CHECK-NEXT: ror r22456; CHECK-NEXT: ret457 %res = ashr i32 %a, 4458 ret i32 %res459}460 461define i32 @ashr_i32_7(i32 %a) {462; CHECK-LABEL: ashr_i32_7:463; CHECK: ; %bb.0:464; CHECK-NEXT: lsl r22465; CHECK-NEXT: rol r23466; CHECK-NEXT: rol r24467; CHECK-NEXT: rol r25468; CHECK-NEXT: sbc r19, r19469; CHECK-NEXT: mov r22, r23470; CHECK-NEXT: mov r23, r24471; CHECK-NEXT: mov r18, r25472; CHECK-NEXT: movw r24, r18473; CHECK-NEXT: ret474 %res = ashr i32 %a, 7475 ret i32 %res476}477 478; TODO: this could be optimized to 4 movs, instead of 5.479define i32 @ashr_i32_8(i32 %a) {480; CHECK-LABEL: ashr_i32_8:481; CHECK: ; %bb.0:482; CHECK-NEXT: mov r19, r25483; CHECK-NEXT: lsl r19484; CHECK-NEXT: sbc r19, r19485; CHECK-NEXT: mov r22, r23486; CHECK-NEXT: mov r23, r24487; CHECK-NEXT: mov r18, r25488; CHECK-NEXT: movw r24, r18489; CHECK-NEXT: ret490 %res = ashr i32 %a, 8491 ret i32 %res492}493 494define i32 @ashr_i32_16(i32 %a) {495; CHECK-LABEL: ashr_i32_16:496; CHECK: ; %bb.0:497; CHECK-NEXT: movw r22, r24498; CHECK-NEXT: lsl r25499; CHECK-NEXT: sbc r25, r25500; CHECK-NEXT: mov r24, r25501; CHECK-NEXT: ret502 %res = ashr i32 %a, 16503 ret i32 %res504}505 506define i32 @ashr_i32_17(i32 %a) {507; CHECK-LABEL: ashr_i32_17:508; CHECK: ; %bb.0:509; CHECK-NEXT: movw r22, r24510; CHECK-NEXT: lsl r25511; CHECK-NEXT: sbc r25, r25512; CHECK-NEXT: asr r23513; CHECK-NEXT: ror r22514; CHECK-NEXT: mov r24, r25515; CHECK-NEXT: ret516 %res = ashr i32 %a, 17517 ret i32 %res518}519 520define i32 @ashr_i32_22(i32 %a) {521; CHECK-LABEL: ashr_i32_22:522; CHECK: ; %bb.0:523; CHECK-NEXT: lsl r24524; CHECK-NEXT: rol r25525; CHECK-NEXT: sbc r18, r18526; CHECK-NEXT: lsl r24527; CHECK-NEXT: rol r25528; CHECK-NEXT: mov r19, r18529; CHECK-NEXT: mov r23, r18530; CHECK-NEXT: rol r23531; CHECK-NEXT: mov r22, r25532; CHECK-NEXT: movw r24, r18533; CHECK-NEXT: ret534 %res = ashr i32 %a, 22535 ret i32 %res536}537 538define i32 @ashr_i32_23(i32 %a) {539; CHECK-LABEL: ashr_i32_23:540; CHECK: ; %bb.0:541; CHECK-NEXT: lsl r24542; CHECK-NEXT: rol r25543; CHECK-NEXT: sbc r23, r23544; CHECK-NEXT: mov r22, r25545; CHECK-NEXT: mov r24, r23546; CHECK-NEXT: mov r25, r23547; CHECK-NEXT: ret548 %res = ashr i32 %a, 23549 ret i32 %res550}551 552define i32 @ashr_i32_30(i32 %a) {553; CHECK-LABEL: ashr_i32_30:554; CHECK: ; %bb.0:555; CHECK-NEXT: lsl r25556; CHECK-NEXT: sbc r23, r23557; CHECK-NEXT: lsl r25558; CHECK-NEXT: mov r22, r23559; CHECK-NEXT: rol r22560; CHECK-NEXT: mov r24, r23561; CHECK-NEXT: mov r25, r23562; CHECK-NEXT: ret563 %res = ashr i32 %a, 30564 ret i32 %res565}566 567define i32 @ashr_i32_31(i32 %a) {568; CHECK-LABEL: ashr_i32_31:569; CHECK: ; %bb.0:570; CHECK-NEXT: lsl r25571; CHECK-NEXT: sbc r22, r22572; CHECK-NEXT: mov r23, r22573; CHECK-NEXT: movw r24, r22574; CHECK-NEXT: ret575 %res = ashr i32 %a, 31576 ret i32 %res577}578