1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -avr-shift-expand -S %s -o - | FileCheck %s 3 4; The avr-shift-expand pass expands large shifts with a non-constant shift 5; amount to a loop. These loops avoid generating a (non-existing) builtin such 6; as __ashlsi3. 7 8target datalayout = "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8" 9target triple = "avr" 10 11define i32 @shl(i32 %value, i32 %amount) addrspace(1) { 12; CHECK-LABEL: @shl( 13; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[AMOUNT:%.*]] to i8 14; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0 15; CHECK-NEXT: br i1 [[TMP2]], label [[SHIFT_DONE:%.*]], label [[SHIFT_LOOP:%.*]] 16; CHECK: shift.loop: 17; CHECK-NEXT: [[TMP3:%.*]] = phi i8 [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[SHIFT_LOOP]] ] 18; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ [[VALUE:%.*]], [[TMP0]] ], [ [[TMP6:%.*]], [[SHIFT_LOOP]] ] 19; CHECK-NEXT: [[TMP5]] = sub i8 [[TMP3]], 1 20; CHECK-NEXT: [[TMP6]] = shl i32 [[TMP4]], 1 21; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP5]], 0 22; CHECK-NEXT: br i1 [[TMP7]], label [[SHIFT_DONE]], label [[SHIFT_LOOP]] 23; CHECK: shift.done: 24; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[VALUE]], [[TMP0]] ], [ [[TMP6]], [[SHIFT_LOOP]] ] 25; CHECK-NEXT: ret i32 [[TMP8]] 26; 27 %result = shl i32 %value, %amount 28 ret i32 %result 29} 30 31define i32 @lshr(i32 %value, i32 %amount) addrspace(1) { 32; CHECK-LABEL: @lshr( 33; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[AMOUNT:%.*]] to i8 34; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0 35; CHECK-NEXT: br i1 [[TMP2]], label [[SHIFT_DONE:%.*]], label [[SHIFT_LOOP:%.*]] 36; CHECK: shift.loop: 37; CHECK-NEXT: [[TMP3:%.*]] = phi i8 [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[SHIFT_LOOP]] ] 38; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ [[VALUE:%.*]], [[TMP0]] ], [ [[TMP6:%.*]], [[SHIFT_LOOP]] ] 39; CHECK-NEXT: [[TMP5]] = sub i8 [[TMP3]], 1 40; CHECK-NEXT: [[TMP6]] = lshr i32 [[TMP4]], 1 41; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP5]], 0 42; CHECK-NEXT: br i1 [[TMP7]], label [[SHIFT_DONE]], label [[SHIFT_LOOP]] 43; CHECK: shift.done: 44; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[VALUE]], [[TMP0]] ], [ [[TMP6]], [[SHIFT_LOOP]] ] 45; CHECK-NEXT: ret i32 [[TMP8]] 46; 47 %result = lshr i32 %value, %amount 48 ret i32 %result 49} 50 51define i32 @ashr(i32 %0, i32 %1) addrspace(1) { 52; CHECK-LABEL: @ashr( 53; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP1:%.*]] to i8 54; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i8 [[TMP3]], 0 55; CHECK-NEXT: br i1 [[TMP4]], label [[SHIFT_DONE:%.*]], label [[SHIFT_LOOP:%.*]] 56; CHECK: shift.loop: 57; CHECK-NEXT: [[TMP5:%.*]] = phi i8 [ [[TMP3]], [[TMP2:%.*]] ], [ [[TMP7:%.*]], [[SHIFT_LOOP]] ] 58; CHECK-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP0:%.*]], [[TMP2]] ], [ [[TMP8:%.*]], [[SHIFT_LOOP]] ] 59; CHECK-NEXT: [[TMP7]] = sub i8 [[TMP5]], 1 60; CHECK-NEXT: [[TMP8]] = ashr i32 [[TMP6]], 1 61; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i8 [[TMP7]], 0 62; CHECK-NEXT: br i1 [[TMP9]], label [[SHIFT_DONE]], label [[SHIFT_LOOP]] 63; CHECK: shift.done: 64; CHECK-NEXT: [[TMP10:%.*]] = phi i32 [ [[TMP0]], [[TMP2]] ], [ [[TMP8]], [[SHIFT_LOOP]] ] 65; CHECK-NEXT: ret i32 [[TMP10]] 66; 67 %3 = ashr i32 %0, %1 68 ret i32 %3 69} 70 71; This function is not modified because it is not an i32. 72define i40 @shl40(i40 %value, i40 %amount) addrspace(1) { 73; CHECK-LABEL: @shl40( 74; CHECK-NEXT: [[RESULT:%.*]] = shl i40 [[VALUE:%.*]], [[AMOUNT:%.*]] 75; CHECK-NEXT: ret i40 [[RESULT]] 76; 77 %result = shl i40 %value, %amount 78 ret i40 %result 79} 80 81; This function isn't either, although perhaps it should. 82define i24 @shl24(i24 %value, i24 %amount) addrspace(1) { 83; CHECK-LABEL: @shl24( 84; CHECK-NEXT: [[RESULT:%.*]] = shl i24 [[VALUE:%.*]], [[AMOUNT:%.*]] 85; CHECK-NEXT: ret i24 [[RESULT]] 86; 87 %result = shl i24 %value, %amount 88 ret i24 %result 89} 90