1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=gvn < %s | FileCheck %s 3; RUN: opt -S -passes=gvn -use-constant-int-for-fixed-length-splat < %s | FileCheck %s 4 5declare void @use(ptr) 6declare void @use.i32(i32) 7 8define void @gep_cse(ptr %p) { 9; CHECK-LABEL: @gep_cse( 10; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 1 11; CHECK-NEXT: [[GEP3:%.*]] = getelementptr i64, ptr [[P]], i64 1 12; CHECK-NEXT: call void @use(ptr [[GEP1]]) 13; CHECK-NEXT: call void @use(ptr [[GEP1]]) 14; CHECK-NEXT: call void @use(ptr [[GEP3]]) 15; CHECK-NEXT: ret void 16; 17 %gep1 = getelementptr i32, ptr %p, i64 1 18 %gep2 = getelementptr i32, ptr %p, i64 1 19 %gep3 = getelementptr i64, ptr %p, i64 1 20 call void @use(ptr %gep1) 21 call void @use(ptr %gep2) 22 call void @use(ptr %gep3) 23 ret void 24} 25 26define void @gep_cse_offset_canonicalization(ptr %p, i64 %idx, i64 %idx2) { 27; CHECK-LABEL: @gep_cse_offset_canonicalization( 28; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 1 29; CHECK-NEXT: [[GEP1_DIFFERENT:%.*]] = getelementptr i8, ptr [[P]], i64 12 30; CHECK-NEXT: call void @use(ptr [[GEP1]]) 31; CHECK-NEXT: call void @use(ptr [[GEP1]]) 32; CHECK-NEXT: call void @use(ptr [[GEP1]]) 33; CHECK-NEXT: call void @use(ptr [[GEP1_DIFFERENT]]) 34; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i64, ptr [[P]], i64 [[IDX:%.*]] 35; CHECK-NEXT: [[GEP2_DIFFERENT:%.*]] = getelementptr { i32, i32, i32 }, ptr [[P]], i64 [[IDX]] 36; CHECK-NEXT: call void @use(ptr [[GEP2]]) 37; CHECK-NEXT: call void @use(ptr [[GEP2]]) 38; CHECK-NEXT: call void @use(ptr [[GEP2_DIFFERENT]]) 39; CHECK-NEXT: [[GEP3:%.*]] = getelementptr { [0 x i32], [0 x i32] }, ptr [[P]], i64 0, i32 0, i64 [[IDX]] 40; CHECK-NEXT: [[GEP3_DIFFERENT:%.*]] = getelementptr { [0 x i32], [0 x i32] }, ptr [[P]], i64 0, i32 0, i64 [[IDX2:%.*]] 41; CHECK-NEXT: call void @use(ptr [[GEP3]]) 42; CHECK-NEXT: call void @use(ptr [[GEP3]]) 43; CHECK-NEXT: call void @use(ptr [[GEP3]]) 44; CHECK-NEXT: call void @use(ptr [[GEP3_DIFFERENT]]) 45; CHECK-NEXT: [[GEP4:%.*]] = getelementptr [4 x i32], ptr [[P]], i64 [[IDX]], i64 [[IDX2]] 46; CHECK-NEXT: [[GEP4_DIFFERENT:%.*]] = getelementptr [4 x float], ptr [[P]], i64 [[IDX2]], i64 [[IDX]] 47; CHECK-NEXT: call void @use(ptr [[GEP4]]) 48; CHECK-NEXT: call void @use(ptr [[GEP4]]) 49; CHECK-NEXT: call void @use(ptr [[GEP4_DIFFERENT]]) 50; CHECK-NEXT: [[GEP5:%.*]] = getelementptr <vscale x 2 x i32>, ptr [[P]], i64 1 51; CHECK-NEXT: [[GEP5_SAME:%.*]] = getelementptr <vscale x 2 x float>, ptr [[P]], i64 1 52; CHECK-NEXT: [[GEP5_DIFFERENT:%.*]] = getelementptr <vscale x 2 x i64>, ptr [[P]], i64 1 53; CHECK-NEXT: call void @use(ptr [[GEP5]]) 54; CHECK-NEXT: call void @use(ptr [[GEP5_SAME]]) 55; CHECK-NEXT: call void @use(ptr [[GEP5_DIFFERENT]]) 56; CHECK-NEXT: [[GEP6:%.*]] = getelementptr [4 x <vscale x 4 x i32>], ptr [[P]], i64 [[IDX]], i64 1 57; CHECK-NEXT: [[GEP6_SAME:%.*]] = getelementptr [4 x <vscale x 4 x float>], ptr [[P]], i64 [[IDX]], i64 1 58; CHECK-NEXT: [[GEP6_DIFFERENT:%.*]] = getelementptr [4 x <vscale x 4 x float>], ptr [[P]], i64 [[IDX2]], i64 1 59; CHECK-NEXT: call void @use(ptr [[GEP6]]) 60; CHECK-NEXT: call void @use(ptr [[GEP6_SAME]]) 61; CHECK-NEXT: call void @use(ptr [[GEP6_DIFFERENT]]) 62; CHECK-NEXT: %gep7 = getelementptr <16 x i32>, ptr %p, i64 1 63; CHECK-NEXT: %gep7.different = getelementptr <16 x i32>, ptr %p, <16 x i64> splat (i64 1) 64; CHECK-NEXT: call void @use(ptr %gep7) 65; CHECK-NEXT: call void @use(<16 x ptr> %gep7.different) 66; CHECK-NEXT: ret void 67; 68 %gep1 = getelementptr i64, ptr %p, i64 1 69 %gep1.same1 = getelementptr i32, ptr %p, i64 2 70 %gep1.same2 = getelementptr i8, ptr %p, i64 8 71 %gep1.different = getelementptr i8, ptr %p, i64 12 72 call void @use(ptr %gep1) 73 call void @use(ptr %gep1.same1) 74 call void @use(ptr %gep1.same2) 75 call void @use(ptr %gep1.different) 76 %gep2 = getelementptr i64, ptr %p, i64 %idx 77 %gep2.same = getelementptr { i32, i32 }, ptr %p, i64 %idx 78 %gep2.different = getelementptr { i32, i32, i32 }, ptr %p, i64 %idx 79 call void @use(ptr %gep2) 80 call void @use(ptr %gep2.same) 81 call void @use(ptr %gep2.different) 82 %gep3 = getelementptr { [0 x i32], [0 x i32] }, ptr %p, i64 0, i32 0, i64 %idx 83 %gep3.same1 = getelementptr { [0 x i32], [0 x i32] }, ptr %p, i64 0, i32 1, i64 %idx 84 %gep3.same2 = getelementptr { [0 x i32], [0 x i32] }, ptr %p, i64 1, i32 0, i64 %idx 85 %gep3.different = getelementptr { [0 x i32], [0 x i32] }, ptr %p, i64 0, i32 0, i64 %idx2 86 call void @use(ptr %gep3) 87 call void @use(ptr %gep3.same1) 88 call void @use(ptr %gep3.same2) 89 call void @use(ptr %gep3.different) 90 %gep4 = getelementptr [4 x i32], ptr %p, i64 %idx, i64 %idx2 91 %gep4.same = getelementptr [4 x float], ptr %p, i64 %idx, i64 %idx2 92 %gep4.different = getelementptr [4 x float], ptr %p, i64 %idx2, i64 %idx 93 call void @use(ptr %gep4) 94 call void @use(ptr %gep4.same) 95 call void @use(ptr %gep4.different) 96 ; TODO: %gep5 and %gep5.same are equivalent as well. 97 %gep5 = getelementptr <vscale x 2 x i32>, ptr %p, i64 1 98 %gep5.same = getelementptr <vscale x 2 x float>, ptr %p, i64 1 99 %gep5.different = getelementptr <vscale x 2 x i64>, ptr %p, i64 1 100 call void @use(ptr %gep5) 101 call void @use(ptr %gep5.same) 102 call void @use(ptr %gep5.different) 103 %gep6 = getelementptr [4 x <vscale x 4 x i32>], ptr %p, i64 %idx, i64 1 104 %gep6.same = getelementptr [4 x <vscale x 4 x float>], ptr %p, i64 %idx, i64 1 105 %gep6.different = getelementptr [4 x <vscale x 4 x float>], ptr %p, i64 %idx2, i64 1 106 call void @use(ptr %gep6) 107 call void @use(ptr %gep6.same) 108 call void @use(ptr %gep6.different) 109 %gep7 = getelementptr <16 x i32>, ptr %p, i64 1 110 %gep7.different = getelementptr <16 x i32>, ptr %p, <16 x i64> splat (i64 1) 111 call void @use(ptr %gep7) 112 call void @use(<16 x ptr> %gep7.different) 113 ret void 114} 115 116define i32 @phi_trans(i1 %c, ptr %p1, ptr %p2) { 117; CHECK-LABEL: @phi_trans( 118; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 119; CHECK: if: 120; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr [[P1:%.*]], i64 1 121; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[GEP1]], align 4 122; CHECK-NEXT: call void @use(i32 [[V1]]) #[[ATTR0:[0-9]+]] 123; CHECK-NEXT: br label [[JOIN:%.*]] 124; CHECK: else: 125; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, ptr [[P2:%.*]], i64 1 126; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[GEP2]], align 4 127; CHECK-NEXT: call void @use(i32 [[V2]]) #[[ATTR0]] 128; CHECK-NEXT: br label [[JOIN]] 129; CHECK: join: 130; CHECK-NEXT: [[V:%.*]] = phi i32 [ [[V1]], [[IF]] ], [ [[V2]], [[ELSE]] ] 131; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[P1]], [[IF]] ], [ [[P2]], [[ELSE]] ] 132; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[PHI]], i64 1 133; CHECK-NEXT: ret i32 [[V]] 134; 135 br i1 %c, label %if, label %else 136 137if: 138 %gep1 = getelementptr i32, ptr %p1, i64 1 139 %v1 = load i32, ptr %gep1 140 call void @use(i32 %v1) readnone 141 br label %join 142 143else: 144 %gep2 = getelementptr i32, ptr %p2, i64 1 145 %v2 = load i32, ptr %gep2 146 call void @use(i32 %v2) readnone 147 br label %join 148 149join: 150 %phi = phi ptr [ %p1, %if ], [ %p2, %else ] 151 %gep = getelementptr i32, ptr %phi, i64 1 152 %v = load i32, ptr %gep 153 ret i32 %v 154} 155 156define i32 @phi_trans_different_types(i1 %c, ptr %p1, ptr %p2) { 157; CHECK-LABEL: @phi_trans_different_types( 158; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 159; CHECK: if: 160; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr [[P1:%.*]], i64 1 161; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[GEP1]], align 4 162; CHECK-NEXT: call void @use.i32(i32 [[V1]]) #[[ATTR0]] 163; CHECK-NEXT: br label [[JOIN:%.*]] 164; CHECK: else: 165; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i64, ptr [[P2:%.*]], i64 1 166; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[GEP2]], align 4 167; CHECK-NEXT: call void @use.i32(i32 [[V2]]) #[[ATTR0]] 168; CHECK-NEXT: [[GEP_PHI_TRANS_INSERT:%.*]] = getelementptr i32, ptr [[P2]], i64 1 169; CHECK-NEXT: [[V_PRE:%.*]] = load i32, ptr [[GEP_PHI_TRANS_INSERT]], align 4 170; CHECK-NEXT: br label [[JOIN]] 171; CHECK: join: 172; CHECK-NEXT: [[V:%.*]] = phi i32 [ [[V1]], [[IF]] ], [ [[V_PRE]], [[ELSE]] ] 173; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[P1]], [[IF]] ], [ [[P2]], [[ELSE]] ] 174; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[PHI]], i64 1 175; CHECK-NEXT: ret i32 [[V]] 176; 177 br i1 %c, label %if, label %else 178 179if: 180 %gep1 = getelementptr i32, ptr %p1, i64 1 181 %v1 = load i32, ptr %gep1 182 call void @use.i32(i32 %v1) readnone 183 br label %join 184 185else: 186 %gep2 = getelementptr i64, ptr %p2, i64 1 187 %v2 = load i32, ptr %gep2 188 call void @use.i32(i32 %v2) readnone 189 br label %join 190 191join: 192 %phi = phi ptr [ %p1, %if ], [ %p2, %else ] 193 %gep = getelementptr i32, ptr %phi, i64 1 194 %v = load i32, ptr %gep 195 ret i32 %v 196} 197 198define i32 @select_pre(ptr %px, ptr %py) { 199; CHECK-LABEL: @select_pre( 200; CHECK-NEXT: [[T2:%.*]] = load i32, ptr [[PY:%.*]], align 4 201; CHECK-NEXT: [[T3:%.*]] = load i32, ptr [[PX:%.*]], align 4 202; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[T2]], [[T3]] 203; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[CMP]], i32 [[T3]], i32 [[T2]] 204; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], ptr [[PX]], ptr [[PY]] 205; CHECK-NEXT: ret i32 [[TMP1]] 206; 207 %t2 = load i32, ptr %py, align 4 208 %t3 = load i32, ptr %px, align 4 209 %cmp = icmp slt i32 %t2, %t3 210 %select = select i1 %cmp, ptr %px, ptr %py 211 %r = load i32, ptr %select, align 4 212 ret i32 %r 213} 214 215define i64 @select_pre_different_types(ptr %px, ptr %py) { 216; CHECK-LABEL: @select_pre_different_types( 217; CHECK-NEXT: [[T2:%.*]] = load i32, ptr [[PY:%.*]], align 4 218; CHECK-NEXT: [[T3:%.*]] = load i32, ptr [[PX:%.*]], align 4 219; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[T2]], [[T3]] 220; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], ptr [[PX]], ptr [[PY]] 221; CHECK-NEXT: [[R:%.*]] = load i64, ptr [[SELECT]], align 4 222; CHECK-NEXT: ret i64 [[R]] 223; 224 %t2 = load i32, ptr %py, align 4 225 %t3 = load i32, ptr %px, align 4 226 %cmp = icmp slt i32 %t2, %t3 227 %select = select i1 %cmp, ptr %px, ptr %py 228 %r = load i64, ptr %select, align 4 229 ret i64 %r 230} 231