Skip to content

Commit ca701a1

Browse files
committed
[InstCombine] Preserve metadata from orig load in select fold.
When replacing load with a select on the address with a select and 2 loads of the values, copy the metadata from the original load to the newly created loads, which are placed at the same place as the original loads. One of the loads will load from an address that won't be accessed originally, but the poison result (if metadata doesn't doesn't hold) will be discarded by the newly created select. We cannot copy any metadata that would cause immediate UB, so !noundef and !invariant.load are skipped. Fixes #115595.
1 parent 6b2ba3f commit ca701a1

File tree

3 files changed

+34
-16
lines changed

3 files changed

+34
-16
lines changed

llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,25 @@ Instruction *InstCombinerImpl::visitLoadInst(LoadInst &LI) {
10601060
V1->setAtomic(LI.getOrdering(), LI.getSyncScopeID());
10611061
V2->setAlignment(Alignment);
10621062
V2->setAtomic(LI.getOrdering(), LI.getSyncScopeID());
1063+
// Can copy any metadata that cannot trigger UB. In particular do not
1064+
// copy !noundef or !invariant.load.
1065+
unsigned SafeMDKinds[] = {LLVMContext::MD_dbg,
1066+
LLVMContext::MD_tbaa,
1067+
LLVMContext::MD_prof,
1068+
LLVMContext::MD_fpmath,
1069+
LLVMContext::MD_tbaa_struct,
1070+
LLVMContext::MD_alias_scope,
1071+
LLVMContext::MD_noalias,
1072+
LLVMContext::MD_nontemporal,
1073+
LLVMContext::MD_mem_parallel_loop_access,
1074+
LLVMContext::MD_access_group,
1075+
LLVMContext::MD_nonnull,
1076+
LLVMContext::MD_align,
1077+
LLVMContext::MD_dereferenceable,
1078+
LLVMContext::MD_dereferenceable_or_null,
1079+
LLVMContext::MD_range};
1080+
V1->copyMetadata(LI, SafeMDKinds);
1081+
V2->copyMetadata(LI, SafeMDKinds);
10631082
return SelectInst::Create(SI->getCondition(), V1, V2);
10641083
}
10651084

llvm/test/Transforms/InstCombine/loadstore-metadata.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,12 @@ entry:
186186
ret i32 %c
187187
}
188188

189-
; FIXME: Should preserve none-UB metadata on loads.
189+
; Preserve none-UB metadata on loads.
190190
define ptr @preserve_load_metadata_after_select_transform1(i1 %c, ptr dereferenceable(8) %a, ptr dereferenceable(8) %b) {
191191
; CHECK-LABEL: @preserve_load_metadata_after_select_transform1(
192192
; CHECK-NEXT: entry:
193-
; CHECK-NEXT: [[B_VAL:%.*]] = load ptr, ptr [[B:%.*]], align 1
194-
; CHECK-NEXT: [[A_VAL:%.*]] = load ptr, ptr [[A:%.*]], align 1
193+
; CHECK-NEXT: [[B_VAL:%.*]] = load ptr, ptr [[B:%.*]], align 1, !tbaa [[TBAA0]], !dereferenceable [[META8]], !llvm.access.group [[META6]]
194+
; CHECK-NEXT: [[A_VAL:%.*]] = load ptr, ptr [[A:%.*]], align 1, !tbaa [[TBAA0]], !dereferenceable [[META8]], !llvm.access.group [[META6]]
195195
; CHECK-NEXT: [[L_SEL:%.*]] = select i1 [[C:%.*]], ptr [[B_VAL]], ptr [[A_VAL]]
196196
; CHECK-NEXT: ret ptr [[L_SEL]]
197197
;
@@ -201,7 +201,7 @@ entry:
201201
ret ptr %l.sel
202202
}
203203

204-
; FIXME: Should preserve none-UB metadata on loads.
204+
; Preserve none-UB metadata on loads.
205205
define i32 @preserve_load_metadata_after_select_transform_range(i1 %c, ptr dereferenceable(8) %a, ptr dereferenceable(8) %b) {
206206
; CHECK-LABEL: @preserve_load_metadata_after_select_transform_range(
207207
; CHECK-NEXT: entry:

llvm/test/Transforms/PhaseOrdering/X86/preserve-access-group.ll

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
55
target triple = "x86_64-unknown-linux-gnu"
66

7-
; FIXME: !llvm.access.group should be preserved, loop should be vectorized.
87
; End-to-end test for https://github.com/llvm/llvm-project/issues/115595.
98
define void @test(i32 noundef %nface, i32 noundef %ncell, ptr noalias noundef %face_cell, ptr noalias noundef %x, ptr noalias noundef %y) #0 {
109
; CHECK-LABEL: define void @test(
@@ -15,16 +14,16 @@ define void @test(i32 noundef %nface, i32 noundef %ncell, ptr noalias noundef %f
1514
; CHECK: [[FOR_BODY_PREHEADER]]:
1615
; CHECK-NEXT: [[TMP0:%.*]] = zext nneg i32 [[NFACE]] to i64
1716
; CHECK-NEXT: [[INVARIANT_GEP:%.*]] = getelementptr inbounds nuw i32, ptr [[FACE_CELL]], i64 [[TMP0]]
18-
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[NFACE]], 4
19-
; CHECK-NEXT: br i1 [[TMP1]], label %[[FOR_BODY_PREHEADER14:.*]], label %[[VECTOR_PH:.*]]
17+
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[NFACE]], 4
18+
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[FOR_BODY_PREHEADER14:.*]], label %[[VECTOR_PH:.*]]
2019
; CHECK: [[VECTOR_PH]]:
21-
; CHECK-NEXT: [[UNROLL_ITER:%.*]] = and i64 [[TMP0]], 2147483644
20+
; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP0]], 2147483644
2221
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
2322
; CHECK: [[VECTOR_BODY]]:
24-
; CHECK-NEXT: [[INDVARS_IV_EPIL:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
25-
; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw i32, ptr [[FACE_CELL]], i64 [[INDVARS_IV_EPIL]]
26-
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP10]], align 4, !tbaa [[TBAA0:![0-9]+]], !llvm.access.group [[ACC_GRP4:![0-9]+]]
27-
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i32, ptr [[INVARIANT_GEP]], i64 [[INDVARS_IV_EPIL]]
23+
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
24+
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i32, ptr [[FACE_CELL]], i64 [[INDEX]]
25+
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP1]], align 4, !tbaa [[TBAA0:![0-9]+]], !llvm.access.group [[ACC_GRP4:![0-9]+]]
26+
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i32, ptr [[INVARIANT_GEP]], i64 [[INDEX]]
2827
; CHECK-NEXT: [[WIDE_LOAD12:%.*]] = load <4 x i32>, ptr [[TMP2]], align 4, !tbaa [[TBAA0]], !llvm.access.group [[ACC_GRP4]]
2928
; CHECK-NEXT: [[TMP3:%.*]] = sext <4 x i32> [[WIDE_LOAD]] to <4 x i64>
3029
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds double, ptr [[Y]], <4 x i64> [[TMP3]]
@@ -35,14 +34,14 @@ define void @test(i32 noundef %nface, i32 noundef %ncell, ptr noalias noundef %f
3534
; CHECK-NEXT: [[TMP7:%.*]] = fcmp fast olt <4 x double> [[WIDE_MASKED_GATHER]], [[WIDE_MASKED_GATHER13]]
3635
; CHECK-NEXT: [[TMP8:%.*]] = select <4 x i1> [[TMP7]], <4 x double> [[WIDE_MASKED_GATHER13]], <4 x double> [[WIDE_MASKED_GATHER]]
3736
; CHECK-NEXT: tail call void @llvm.masked.scatter.v4f64.v4p0(<4 x double> [[TMP8]], <4 x ptr> [[TMP4]], i32 8, <4 x i1> splat (i1 true)), !tbaa [[TBAA5]], !llvm.access.group [[ACC_GRP4]]
38-
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDVARS_IV_EPIL]], 4
39-
; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[UNROLL_ITER]]
37+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
38+
; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
4039
; CHECK-NEXT: br i1 [[TMP9]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP7:![0-9]+]]
4140
; CHECK: [[MIDDLE_BLOCK]]:
42-
; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[UNROLL_ITER]], [[TMP0]]
41+
; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N_VEC]], [[TMP0]]
4342
; CHECK-NEXT: br i1 [[CMP_N]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY_PREHEADER14]]
4443
; CHECK: [[FOR_BODY_PREHEADER14]]:
45-
; CHECK-NEXT: [[INDVARS_IV_PH:%.*]] = phi i64 [ 0, %[[FOR_BODY_PREHEADER]] ], [ [[UNROLL_ITER]], %[[MIDDLE_BLOCK]] ]
44+
; CHECK-NEXT: [[INDVARS_IV_PH:%.*]] = phi i64 [ 0, %[[FOR_BODY_PREHEADER]] ], [ [[N_VEC]], %[[MIDDLE_BLOCK]] ]
4645
; CHECK-NEXT: br label %[[FOR_BODY:.*]]
4746
; CHECK: [[FOR_COND_CLEANUP]]:
4847
; CHECK-NEXT: ret void

0 commit comments

Comments
 (0)