1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -instcombine < %s | FileCheck %s 3 4declare void @foo() 5declare void @bar() 6declare void @baz() 7 8declare void @usei32(i32) 9declare void @usei32i32agg({ i32, i32 }) 10 11; Most basic test - we explode the original aggregate into it's elements, 12; and then merge them back together exactly the way they were. 13; We should just return the source aggregate. 14define { i32, i32 } @test0({ i32, i32 } %srcagg) { 15; CHECK-LABEL: @test0( 16; CHECK-NEXT: ret { i32, i32 } [[SRCAGG:%.*]] 17; 18 %i0 = extractvalue { i32, i32 } %srcagg, 0 19 %i1 = extractvalue { i32, i32 } %srcagg, 1 20 %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0 21 %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1 22 ret { i32, i32 } %i3 23} 24 25; Arrays are still aggregates 26define [2 x i32] @test1([2 x i32] %srcagg) { 27; CHECK-LABEL: @test1( 28; CHECK-NEXT: ret [2 x i32] [[SRCAGG:%.*]] 29; 30 %i0 = extractvalue [2 x i32] %srcagg, 0 31 %i1 = extractvalue [2 x i32] %srcagg, 1 32 %i2 = insertvalue [2 x i32] undef, i32 %i0, 0 33 %i3 = insertvalue [2 x i32] %i2, i32 %i1, 1 34 ret [2 x i32] %i3 35} 36 37; Right now we don't deal with case where there are more than 2 elements. 38; FIXME: should we? 39define [3 x i32] @test2([3 x i32] %srcagg) { 40; CHECK-LABEL: @test2( 41; CHECK-NEXT: [[I0:%.*]] = extractvalue [3 x i32] [[SRCAGG:%.*]], 0 42; CHECK-NEXT: [[I1:%.*]] = extractvalue [3 x i32] [[SRCAGG]], 1 43; CHECK-NEXT: [[I2:%.*]] = extractvalue [3 x i32] [[SRCAGG]], 2 44; CHECK-NEXT: [[I3:%.*]] = insertvalue [3 x i32] undef, i32 [[I0]], 0 45; CHECK-NEXT: [[I4:%.*]] = insertvalue [3 x i32] [[I3]], i32 [[I1]], 1 46; CHECK-NEXT: [[I5:%.*]] = insertvalue [3 x i32] [[I4]], i32 [[I2]], 2 47; CHECK-NEXT: ret [3 x i32] [[I5]] 48; 49 %i0 = extractvalue [3 x i32] %srcagg, 0 50 %i1 = extractvalue [3 x i32] %srcagg, 1 51 %i2 = extractvalue [3 x i32] %srcagg, 2 52 %i3 = insertvalue [3 x i32] undef, i32 %i0, 0 53 %i4 = insertvalue [3 x i32] %i3, i32 %i1, 1 54 %i5 = insertvalue [3 x i32] %i4, i32 %i2, 2 55 ret [3 x i32] %i5 56} 57 58; Likewise, we only deal with a single-level aggregates. 59; FIXME: should we? 60define {{ i32, i32 }} @test3({{ i32, i32 }} %srcagg) { 61; CHECK-LABEL: @test3( 62; CHECK-NEXT: [[I0:%.*]] = extractvalue { { i32, i32 } } [[SRCAGG:%.*]], 0, 0 63; CHECK-NEXT: [[I1:%.*]] = extractvalue { { i32, i32 } } [[SRCAGG]], 0, 1 64; CHECK-NEXT: [[I2:%.*]] = insertvalue { { i32, i32 } } undef, i32 [[I0]], 0, 0 65; CHECK-NEXT: [[I3:%.*]] = insertvalue { { i32, i32 } } [[I2]], i32 [[I1]], 0, 1 66; CHECK-NEXT: ret { { i32, i32 } } [[I3]] 67; 68 %i0 = extractvalue {{ i32, i32 }} %srcagg, 0, 0 69 %i1 = extractvalue {{ i32, i32 }} %srcagg, 0, 1 70 %i2 = insertvalue {{ i32, i32 }} undef, i32 %i0, 0, 0 71 %i3 = insertvalue {{ i32, i32 }} %i2, i32 %i1, 0, 1 72 ret {{ i32, i32 }} %i3 73} 74 75; This is fine, however, all elements are on the same level 76define { i32, { i32 } } @test4({ i32, { i32 } } %srcagg) { 77; CHECK-LABEL: @test4( 78; CHECK-NEXT: ret { i32, { i32 } } [[SRCAGG:%.*]] 79; 80 %i0 = extractvalue { i32, { i32 } } %srcagg, 0 81 %i1 = extractvalue { i32, { i32 } } %srcagg, 1 82 %i2 = insertvalue { i32, { i32 } } undef, i32 %i0, 0 83 %i3 = insertvalue { i32, { i32 } } %i2, { i32 } %i1, 1 84 ret { i32, { i32 } } %i3 85} 86 87; All element of the newly-created aggregate must come from the same base 88; aggregate. Here the second element comes from some other origin. 89define { i32, i32 } @negative_test5({ i32, i32 } %srcagg, i32 %replacement) { 90; CHECK-LABEL: @negative_test5( 91; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0 92; CHECK-NEXT: [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0 93; CHECK-NEXT: [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[REPLACEMENT:%.*]], 1 94; CHECK-NEXT: ret { i32, i32 } [[I3]] 95; 96 %i0 = extractvalue { i32, i32 } %srcagg, 0 97 ; %i1 = extractvalue { i32, i32 } %srcagg, 1 98 %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0 99 %i3 = insertvalue { i32, i32 } %i2, i32 %replacement, 1 100 ret { i32, i32 } %i3 101} 102 103; Here we don't know the value of second element of %otheragg, 104define { i32, i32 } @negative_test6({ i32, i32 } %srcagg, { i32, i32 } %otheragg) { 105; CHECK-LABEL: @negative_test6( 106; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0 107; CHECK-NEXT: [[I2:%.*]] = insertvalue { i32, i32 } [[OTHERAGG:%.*]], i32 [[I0]], 0 108; CHECK-NEXT: ret { i32, i32 } [[I2]] 109; 110 %i0 = extractvalue { i32, i32 } %srcagg, 0 111 ; %i1 = extractvalue { i32, i32 } %srcagg, 1 112 %i2 = insertvalue { i32, i32 } %otheragg, i32 %i0, 0 113 ret { i32, i32 } %i2 114} 115 116; All element of the newly-created aggregate must come from the same base 117; aggregate. Here different elements come from different base aggregates. 118define { i32, i32 } @negative_test7({ i32, i32 } %srcagg0, { i32, i32 } %srcagg1) { 119; CHECK-LABEL: @negative_test7( 120; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG0:%.*]], 0 121; CHECK-NEXT: [[I3:%.*]] = extractvalue { i32, i32 } [[SRCAGG1:%.*]], 1 122; CHECK-NEXT: [[I4:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0 123; CHECK-NEXT: [[I5:%.*]] = insertvalue { i32, i32 } [[I4]], i32 [[I3]], 1 124; CHECK-NEXT: ret { i32, i32 } [[I5]] 125; 126 %i0 = extractvalue { i32, i32 } %srcagg0, 0 127 ; %i1 = extractvalue { i32, i32 } %srcagg0, 1 128 129 ; %i2 = extractvalue { i32, i32 } %srcagg1, 0 130 %i3 = extractvalue { i32, i32 } %srcagg1, 1 131 132 %i4 = insertvalue { i32, i32 } undef, i32 %i0, 0 133 %i5 = insertvalue { i32, i32 } %i4, i32 %i3, 1 134 ret { i32, i32 } %i5 135} 136 137; Here the element order is swapped as compared to the base aggregate. 138define { i32, i32 } @negative_test8({ i32, i32 } %srcagg) { 139; CHECK-LABEL: @negative_test8( 140; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0 141; CHECK-NEXT: [[I1:%.*]] = extractvalue { i32, i32 } [[SRCAGG]], 1 142; CHECK-NEXT: [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 1 143; CHECK-NEXT: [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[I1]], 0 144; CHECK-NEXT: ret { i32, i32 } [[I3]] 145; 146 %i0 = extractvalue { i32, i32 } %srcagg, 0 147 %i1 = extractvalue { i32, i32 } %srcagg, 1 148 %i2 = insertvalue { i32, i32 } undef, i32 %i0, 1 149 %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 0 150 ret { i32, i32 } %i3 151} 152 153; Here both elements of the new aggregate come from the same element of the old aggregate. 154define { i32, i32 } @negative_test9({ i32, i32 } %srcagg) { 155; CHECK-LABEL: @negative_test9( 156; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0 157; CHECK-NEXT: [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0 158; CHECK-NEXT: [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[I0]], 1 159; CHECK-NEXT: ret { i32, i32 } [[I3]] 160; 161 %i0 = extractvalue { i32, i32 } %srcagg, 0 162 ; %i1 = extractvalue { i32, i32 } %srcagg, 1 163 %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0 164 %i3 = insertvalue { i32, i32 } %i2, i32 %i0, 1 165 ret { i32, i32 } %i3 166} 167 168; Here the second element of the new aggregate is undef, , so we must keep this as-is, because in %srcagg it might be poison. 169; FIXME: defer to noundef attribute on %srcagg 170define { i32, i32 } @negative_test10({ i32, i32 } %srcagg) { 171; CHECK-LABEL: @negative_test10( 172; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0 173; CHECK-NEXT: [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0 174; CHECK-NEXT: ret { i32, i32 } [[I2]] 175; 176 %i0 = extractvalue { i32, i32 } %srcagg, 0 177 ; %i1 = extractvalue { i32, i32 } %srcagg, 1 178 %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0 179 ret { i32, i32 } %i2 180} 181 182; Here the second element of the new aggregate is undef, so we must keep this as-is, because in %srcagg it might be poison. 183; FIXME: defer to noundef attribute on %srcagg 184define { i32, i32 } @negative_test11({ i32, i32 } %srcagg) { 185; CHECK-LABEL: @negative_test11( 186; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0 187; CHECK-NEXT: [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0 188; CHECK-NEXT: [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 undef, 1 189; CHECK-NEXT: ret { i32, i32 } [[I3]] 190; 191 %i0 = extractvalue { i32, i32 } %srcagg, 0 192 ; %i1 = extractvalue { i32, i32 } %srcagg, 1 193 %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0 194 %i3 = insertvalue { i32, i32 } %i2, i32 undef, 1 195 ret { i32, i32 } %i3 196} 197 198; This fold does not care whether or not intermediate instructions have extra uses. 199define { i32, i32 } @test12({ i32, i32 } %srcagg) { 200; CHECK-LABEL: @test12( 201; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0 202; CHECK-NEXT: call void @usei32(i32 [[I0]]) 203; CHECK-NEXT: [[I1:%.*]] = extractvalue { i32, i32 } [[SRCAGG]], 1 204; CHECK-NEXT: call void @usei32(i32 [[I1]]) 205; CHECK-NEXT: [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0 206; CHECK-NEXT: call void @usei32i32agg({ i32, i32 } [[I2]]) 207; CHECK-NEXT: ret { i32, i32 } [[SRCAGG]] 208; 209 %i0 = extractvalue { i32, i32 } %srcagg, 0 210 call void @usei32(i32 %i0) 211 %i1 = extractvalue { i32, i32 } %srcagg, 1 212 call void @usei32(i32 %i1) 213 %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0 214 call void @usei32i32agg({ i32, i32 } %i2) 215 %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1 216 ret { i32, i32 } %i3 217} 218 219; Even though we originally store %i1 into first element, it is later 220; overwritten with %i0, so all is fine. 221define { i32, i32 } @test13({ i32, i32 } %srcagg) { 222; CHECK-LABEL: @test13( 223; CHECK-NEXT: ret { i32, i32 } [[SRCAGG:%.*]] 224; 225 %i0 = extractvalue { i32, i32 } %srcagg, 0 226 %i1 = extractvalue { i32, i32 } %srcagg, 1 227 %i2 = insertvalue { i32, i32 } undef, i32 %i1, 0 228 %i3 = insertvalue { i32, i32 } %i2, i32 %i0, 0 229 %i4 = insertvalue { i32, i32 } %i3, i32 %i1, 1 230 ret { i32, i32 } %i4 231} 232 233; The aggregate type must match exactly between the original and recreation. 234define { i32, i32 } @negative_test14({ i32, i32, i32 } %srcagg) { 235; CHECK-LABEL: @negative_test14( 236; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32, i32 } [[SRCAGG:%.*]], 0 237; CHECK-NEXT: [[I1:%.*]] = extractvalue { i32, i32, i32 } [[SRCAGG]], 1 238; CHECK-NEXT: [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0 239; CHECK-NEXT: [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[I1]], 1 240; CHECK-NEXT: ret { i32, i32 } [[I3]] 241; 242 %i0 = extractvalue { i32, i32, i32 } %srcagg, 0 243 %i1 = extractvalue { i32, i32, i32 } %srcagg, 1 244 %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0 245 %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1 246 ret { i32, i32 } %i3 247} 248define { i32, i32 } @negative_test15({ i32, {i32} } %srcagg) { 249; CHECK-LABEL: @negative_test15( 250; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, { i32 } } [[SRCAGG:%.*]], 0 251; CHECK-NEXT: [[I1:%.*]] = extractvalue { i32, { i32 } } [[SRCAGG]], 1, 0 252; CHECK-NEXT: [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0 253; CHECK-NEXT: [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[I1]], 1 254; CHECK-NEXT: ret { i32, i32 } [[I3]] 255; 256 %i0 = extractvalue { i32, {i32} } %srcagg, 0 257 %i1 = extractvalue { i32, {i32} } %srcagg, 1, 0 258 %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0 259 %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1 260 ret { i32, i32 } %i3 261} 262 263; Just because there are predecessors doesn't mean we should look into them. 264define { i32, i32 } @test16({ i32, i32 } %srcagg) { 265; CHECK-LABEL: @test16( 266; CHECK-NEXT: entry: 267; CHECK-NEXT: br label [[END:%.*]] 268; CHECK: end: 269; CHECK-NEXT: ret { i32, i32 } [[SRCAGG:%.*]] 270; 271entry: 272 br label %end 273end: 274 %i0 = extractvalue { i32, i32 } %srcagg, 0 275 %i1 = extractvalue { i32, i32 } %srcagg, 1 276 %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0 277 %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1 278 ret { i32, i32 } %i3 279} 280 281; Again, we should first try to perform local reasoning, without looking to predecessors. 282define { i32, i32 } @test17({ i32, i32 } %srcagg0, { i32, i32 } %srcagg1, i1 %c) { 283; CHECK-LABEL: @test17( 284; CHECK-NEXT: entry: 285; CHECK-NEXT: br i1 [[C:%.*]], label [[INTERMEDIATE:%.*]], label [[END:%.*]] 286; CHECK: intermediate: 287; CHECK-NEXT: br label [[END]] 288; CHECK: end: 289; CHECK-NEXT: [[SRCAGG_PHI:%.*]] = phi { i32, i32 } [ [[SRCAGG0:%.*]], [[ENTRY:%.*]] ], [ [[SRCAGG1:%.*]], [[INTERMEDIATE]] ] 290; CHECK-NEXT: ret { i32, i32 } [[SRCAGG_PHI]] 291; 292entry: 293 br i1 %c, label %intermediate, label %end 294intermediate: 295 br label %end 296end: 297 %srcagg.phi = phi { i32, i32 } [ %srcagg0, %entry ], [ %srcagg1, %intermediate ] 298 %i0 = extractvalue { i32, i32 } %srcagg.phi, 0 299 %i1 = extractvalue { i32, i32 } %srcagg.phi, 1 300 %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0 301 %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1 302 ret { i32, i32 } %i3 303} 304