1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -slsr -gvn -S | FileCheck %s 3; RUN: opt < %s -passes='slsr,gvn' -S | FileCheck %s 4 5target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64" 6 7define void @shl(i32 %b, i32 %s) { 8; CHECK-LABEL: @shl( 9; CHECK-NEXT: [[T1:%.*]] = add i32 [[B:%.*]], [[S:%.*]] 10; CHECK-NEXT: call void @foo(i32 [[T1]]) 11; CHECK-NEXT: [[T2:%.*]] = add i32 [[T1]], [[S]] 12; CHECK-NEXT: call void @foo(i32 [[T2]]) 13; CHECK-NEXT: ret void 14; 15 %t1 = add i32 %b, %s 16 call void @foo(i32 %t1) 17 %s2 = shl i32 %s, 1 18 %t2 = add i32 %b, %s2 19 call void @foo(i32 %t2) 20 ret void 21} 22 23define void @stride_is_2s(i32 %b, i32 %s) { 24; CHECK-LABEL: @stride_is_2s( 25; CHECK-NEXT: [[S2:%.*]] = shl i32 [[S:%.*]], 1 26; CHECK-NEXT: [[T1:%.*]] = add i32 [[B:%.*]], [[S2]] 27; CHECK-NEXT: call void @foo(i32 [[T1]]) 28; CHECK-NEXT: [[T2:%.*]] = add i32 [[T1]], [[S2]] 29; CHECK-NEXT: call void @foo(i32 [[T2]]) 30; CHECK-NEXT: [[T3:%.*]] = add i32 [[T2]], [[S2]] 31; CHECK-NEXT: call void @foo(i32 [[T3]]) 32; CHECK-NEXT: ret void 33; 34 %s2 = shl i32 %s, 1 35 %t1 = add i32 %b, %s2 36 call void @foo(i32 %t1) 37 %s4 = shl i32 %s, 2 38 %t2 = add i32 %b, %s4 39 call void @foo(i32 %t2) 40 %s6 = mul i32 %s, 6 41 %t3 = add i32 %b, %s6 42 call void @foo(i32 %t3) 43 ret void 44} 45 46define void @stride_is_3s(i32 %b, i32 %s) { 47; CHECK-LABEL: @stride_is_3s( 48; CHECK-NEXT: [[T1:%.*]] = add i32 [[S:%.*]], [[B:%.*]] 49; CHECK-NEXT: call void @foo(i32 [[T1]]) 50; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[S]], 3 51; CHECK-NEXT: [[T2:%.*]] = add i32 [[T1]], [[TMP1]] 52; CHECK-NEXT: call void @foo(i32 [[T2]]) 53; CHECK-NEXT: [[T3:%.*]] = add i32 [[T2]], [[TMP1]] 54; CHECK-NEXT: call void @foo(i32 [[T3]]) 55; CHECK-NEXT: ret void 56; 57 %t1 = add i32 %s, %b 58 call void @foo(i32 %t1) 59 %s4 = shl i32 %s, 2 60 %t2 = add i32 %s4, %b 61 call void @foo(i32 %t2) 62 %s7 = mul i32 %s, 7 63 %t3 = add i32 %s7, %b 64 call void @foo(i32 %t3) 65 ret void 66} 67 68; foo(b + 6 * s); 69; foo(b + 4 * s); 70; foo(b + 2 * s); 71; => 72; t1 = b + 6 * s; 73; foo(t1); 74; s2 = 2 * s; 75; t2 = t1 - s2; 76; foo(t2); 77; t3 = t2 - s2; 78; foo(t3); 79define void @stride_is_minus_2s(i32 %b, i32 %s) { 80; CHECK-LABEL: @stride_is_minus_2s( 81; CHECK-NEXT: [[S6:%.*]] = mul i32 [[S:%.*]], 6 82; CHECK-NEXT: [[T1:%.*]] = add i32 [[B:%.*]], [[S6]] 83; CHECK-NEXT: call void @foo(i32 [[T1]]) 84; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[S]], 1 85; CHECK-NEXT: [[T2:%.*]] = sub i32 [[T1]], [[TMP1]] 86; CHECK-NEXT: call void @foo(i32 [[T2]]) 87; CHECK-NEXT: [[T3:%.*]] = sub i32 [[T2]], [[TMP1]] 88; CHECK-NEXT: call void @foo(i32 [[T3]]) 89; CHECK-NEXT: ret void 90; 91 %s6 = mul i32 %s, 6 92 %t1 = add i32 %b, %s6 93 call void @foo(i32 %t1) 94 %s4 = shl i32 %s, 2 95 %t2 = add i32 %b, %s4 96 call void @foo(i32 %t2) 97 %s2 = shl i32 %s, 1 98 %t3 = add i32 %b, %s2 99 call void @foo(i32 %t3) 100 ret void 101} 102 103; TODO: This pass is targeted at simple address-calcs, so it is artificially limited to 104; match scalar values. The code could be modified to handle vector types too. 105 106define void @stride_is_minus_2s_vec(<2 x i32> %b, <2 x i32> %s) { 107; CHECK-LABEL: @stride_is_minus_2s_vec( 108; CHECK-NEXT: [[S6:%.*]] = mul <2 x i32> [[S:%.*]], <i32 6, i32 6> 109; CHECK-NEXT: [[T1:%.*]] = add <2 x i32> [[B:%.*]], [[S6]] 110; CHECK-NEXT: call void @voo(<2 x i32> [[T1]]) 111; CHECK-NEXT: [[S4:%.*]] = shl <2 x i32> [[S]], <i32 2, i32 2> 112; CHECK-NEXT: [[T2:%.*]] = add <2 x i32> [[B]], [[S4]] 113; CHECK-NEXT: call void @voo(<2 x i32> [[T2]]) 114; CHECK-NEXT: [[S2:%.*]] = shl <2 x i32> [[S]], <i32 1, i32 1> 115; CHECK-NEXT: [[T3:%.*]] = add <2 x i32> [[B]], [[S2]] 116; CHECK-NEXT: call void @voo(<2 x i32> [[T3]]) 117; CHECK-NEXT: ret void 118; 119 %s6 = mul <2 x i32> %s, <i32 6, i32 6> 120 %t1 = add <2 x i32> %b, %s6 121 call void @voo(<2 x i32> %t1) 122 %s4 = shl <2 x i32> %s, <i32 2, i32 2> 123 %t2 = add <2 x i32> %b, %s4 124 call void @voo(<2 x i32> %t2) 125 %s2 = shl <2 x i32> %s, <i32 1, i32 1> 126 %t3 = add <2 x i32> %b, %s2 127 call void @voo(<2 x i32> %t3) 128 ret void 129} 130 131; t = b + (s << 3); 132; foo(t); 133; foo(b + s); 134; 135; do not rewrite b + s to t - 7 * s because the latter is more complicated. 136define void @simple_enough(i32 %b, i32 %s) { 137; CHECK-LABEL: @simple_enough( 138; CHECK-NEXT: [[S8:%.*]] = shl i32 [[S:%.*]], 3 139; CHECK-NEXT: [[T1:%.*]] = add i32 [[B:%.*]], [[S8]] 140; CHECK-NEXT: call void @foo(i32 [[T1]]) 141; CHECK-NEXT: [[T2:%.*]] = add i32 [[B]], [[S]] 142; CHECK-NEXT: call void @foo(i32 [[T2]]) 143; CHECK-NEXT: ret void 144; 145 %s8 = shl i32 %s, 3 146 %t1 = add i32 %b, %s8 147 call void @foo(i32 %t1) 148 %t2 = add i32 %b, %s 149 call void @foo(i32 %t2) 150 ret void 151} 152 153define void @slsr_strided_add_128bit(i128 %b, i128 %s) { 154; CHECK-LABEL: @slsr_strided_add_128bit( 155; CHECK-NEXT: [[S125:%.*]] = shl i128 [[S:%.*]], 125 156; CHECK-NEXT: [[T1:%.*]] = add i128 [[B:%.*]], [[S125]] 157; CHECK-NEXT: call void @bar(i128 [[T1]]) 158; CHECK-NEXT: [[T2:%.*]] = add i128 [[T1]], [[S125]] 159; CHECK-NEXT: call void @bar(i128 [[T2]]) 160; CHECK-NEXT: ret void 161; 162 %s125 = shl i128 %s, 125 163 %s126 = shl i128 %s, 126 164 %t1 = add i128 %b, %s125 165 call void @bar(i128 %t1) 166 %t2 = add i128 %b, %s126 167 call void @bar(i128 %t2) 168 ret void 169} 170 171declare void @foo(i32) 172declare void @voo(<2 x i32>) 173declare void @bar(i128) 174