1 ; RUN: opt < %s -slsr -gvn -S | FileCheck %s 2 3 target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64" 4 5 define void @slsr1(i32 %b, i32 %s) { 6 ; CHECK-LABEL: @slsr1( 7 ; foo(b * s); 8 %mul0 = mul i32 %b, %s 9 ; CHECK: mul i32 10 ; CHECK-NOT: mul i32 11 call void @foo(i32 %mul0) 12 13 ; foo((b + 1) * s); 14 %b1 = add i32 %b, 1 15 %mul1 = mul i32 %b1, %s 16 call void @foo(i32 %mul1) 17 18 ; foo((b + 2) * s); 19 %b2 = add i32 %b, 2 20 %mul2 = mul i32 %b2, %s 21 call void @foo(i32 %mul2) 22 23 ret void 24 } 25 26 define void @non_canonicalized(i32 %b, i32 %s) { 27 ; CHECK-LABEL: @non_canonicalized( 28 ; foo(b * s); 29 %mul0 = mul i32 %b, %s 30 ; CHECK: mul i32 31 ; CHECK-NOT: mul i32 32 call void @foo(i32 %mul0) 33 34 ; foo((1 + b) * s); 35 %b1 = add i32 1, %b 36 %mul1 = mul i32 %b1, %s 37 call void @foo(i32 %mul1) 38 39 ; foo((2 + b) * s); 40 %b2 = add i32 2, %b 41 %mul2 = mul i32 %b2, %s 42 call void @foo(i32 %mul2) 43 44 ret void 45 } 46 47 define void @or(i32 %a, i32 %s) { 48 %b = shl i32 %a, 1 49 ; CHECK-LABEL: @or( 50 ; foo(b * s); 51 %mul0 = mul i32 %b, %s 52 ; CHECK: [[base:[^ ]+]] = mul i32 53 call void @foo(i32 %mul0) 54 55 ; foo((b | 1) * s); 56 %b1 = or i32 %b, 1 57 %mul1 = mul i32 %b1, %s 58 ; CHECK: add i32 [[base]], %s 59 call void @foo(i32 %mul1) 60 61 ; foo((b | 2) * s); 62 %b2 = or i32 %b, 2 63 %mul2 = mul i32 %b2, %s 64 ; CHECK: mul i32 %b2, %s 65 call void @foo(i32 %mul2) 66 67 ret void 68 } 69 70 ; foo(a * b) 71 ; foo((a + 1) * b) 72 ; foo(a * (b + 1)) 73 ; foo((a + 1) * (b + 1)) 74 define void @slsr2(i32 %a, i32 %b) { 75 ; CHECK-LABEL: @slsr2( 76 %a1 = add i32 %a, 1 77 %b1 = add i32 %b, 1 78 %mul0 = mul i32 %a, %b 79 ; CHECK: mul i32 80 ; CHECK-NOT: mul i32 81 %mul1 = mul i32 %a1, %b 82 %mul2 = mul i32 %a, %b1 83 %mul3 = mul i32 %a1, %b1 84 85 call void @foo(i32 %mul0) 86 call void @foo(i32 %mul1) 87 call void @foo(i32 %mul2) 88 call void @foo(i32 %mul3) 89 90 ret void 91 } 92 93 ; The bump is a multiple of the stride. 94 ; 95 ; foo(b * s); 96 ; foo((b + 2) * s); 97 ; foo((b + 4) * s); 98 ; => 99 ; mul0 = b * s; 100 ; bump = s * 2; 101 ; mul1 = mul0 + bump; // GVN ensures mul1 and mul2 use the same bump. 102 ; mul2 = mul1 + bump; 103 define void @slsr3(i32 %b, i32 %s) { 104 ; CHECK-LABEL: @slsr3( 105 %mul0 = mul i32 %b, %s 106 ; CHECK: mul i32 107 call void @foo(i32 %mul0) 108 109 %b1 = add i32 %b, 2 110 %mul1 = mul i32 %b1, %s 111 ; CHECK: [[BUMP:%[a-zA-Z0-9]+]] = shl i32 %s, 1 112 ; CHECK: %mul1 = add i32 %mul0, [[BUMP]] 113 call void @foo(i32 %mul1) 114 115 %b2 = add i32 %b, 4 116 %mul2 = mul i32 %b2, %s 117 ; CHECK: %mul2 = add i32 %mul1, [[BUMP]] 118 call void @foo(i32 %mul2) 119 120 ret void 121 } 122 123 ; Do not rewrite a candidate if its potential basis does not dominate it. 124 ; 125 ; if (cond) 126 ; foo(a * b); 127 ; foo((a + 1) * b); 128 define void @not_dominate(i1 %cond, i32 %a, i32 %b) { 129 ; CHECK-LABEL: @not_dominate( 130 entry: 131 %a1 = add i32 %a, 1 132 br i1 %cond, label %then, label %merge 133 134 then: 135 %mul0 = mul i32 %a, %b 136 ; CHECK: %mul0 = mul i32 %a, %b 137 call void @foo(i32 %mul0) 138 br label %merge 139 140 merge: 141 %mul1 = mul i32 %a1, %b 142 ; CHECK: %mul1 = mul i32 %a1, %b 143 call void @foo(i32 %mul1) 144 ret void 145 } 146 147 declare void @foo(i32) 148