[NFC][SROA] Add test for select speculation failures
authorRoman Lebedev <lebedev.ri@gmail.com>
Thu, 17 Nov 2022 17:02:12 +0000 (20:02 +0300)
committerRoman Lebedev <lebedev.ri@gmail.com>
Thu, 17 Nov 2022 17:48:27 +0000 (20:48 +0300)
llvm/test/Transforms/SROA/select-load.ll

index e6d29b0..376e44f 100644 (file)
@@ -58,3 +58,69 @@ entry:
 
 declare void @foo_i8(ptr)
 declare void @foo_i32(ptr)
+
+; Lifetime intrinsics should not prevent dereferenceability inferrence.
+define i32 @interfering_lifetime(ptr %data, i64 %indvars.iv) {
+; CHECK-LABEL: @interfering_lifetime(
+; CHECK-NEXT:    [[MIN:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV:%.*]]
+; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[MIN]])
+; CHECK-NEXT:    store i32 0, ptr [[MIN]], align 4
+; CHECK-NEXT:    [[CMP_I_I:%.*]] = icmp slt i32 [[I1]], 0
+; CHECK-NEXT:    [[I2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[I1]], i32 0)
+; CHECK-NEXT:    [[__B___A_I_I:%.*]] = select i1 [[CMP_I_I]], ptr [[MIN]], ptr [[ARRAYIDX]]
+; CHECK-NEXT:    [[I3:%.*]] = load i32, ptr [[__B___A_I_I]], align 4
+; CHECK-NEXT:    ret i32 [[I3]]
+;
+  %min = alloca i32, align 4
+  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
+  %i1 = load i32, ptr %arrayidx, align 4
+  call void @llvm.lifetime.start.p0(i64 4, ptr %min)
+  store i32 0, ptr %min, align 4
+  %cmp.i.i = icmp slt i32 %i1, 0
+  %i2 = tail call i32 @llvm.smax.i32(i32 %i1, i32 0)
+  %__b.__a.i.i = select i1 %cmp.i.i, ptr %min, ptr %arrayidx
+  %i3 = load i32, ptr %__b.__a.i.i, align 4
+  ret i32 %i3
+}
+
+; We should recursively evaluate select's.
+define i32 @clamp_load_to_constant_range(ptr %data, i64 %indvars.iv) {
+; CHECK-LABEL: @clamp_load_to_constant_range(
+; CHECK-NEXT:    [[MIN:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    [[MAX:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV:%.*]]
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[MIN]])
+; CHECK-NEXT:    store i32 0, ptr [[MIN]], align 4
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[MAX]])
+; CHECK-NEXT:    store i32 4095, ptr [[MAX]], align 4
+; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    [[CMP_I_I:%.*]] = icmp slt i32 [[I1]], 0
+; CHECK-NEXT:    [[I2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[I1]], i32 0)
+; CHECK-NEXT:    [[__B___A_I_I:%.*]] = select i1 [[CMP_I_I]], ptr [[MIN]], ptr [[ARRAYIDX]]
+; CHECK-NEXT:    [[CMP_I1_I:%.*]] = icmp ugt i32 [[I2]], 4095
+; CHECK-NEXT:    [[__B___A_I2_I:%.*]] = select i1 [[CMP_I1_I]], ptr [[MAX]], ptr [[__B___A_I_I]]
+; CHECK-NEXT:    [[I3:%.*]] = load i32, ptr [[__B___A_I2_I]], align 4
+; CHECK-NEXT:    ret i32 [[I3]]
+;
+  %min = alloca i32, align 4
+  %max = alloca i32, align 4
+  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
+  call void @llvm.lifetime.start.p0(i64 4, ptr %min)
+  store i32 0, ptr %min, align 4
+  call void @llvm.lifetime.start.p0(i64 4, ptr %max)
+  store i32 4095, ptr %max, align 4
+  %i1 = load i32, ptr %arrayidx, align 4
+  %cmp.i.i = icmp slt i32 %i1, 0
+  %i2 = tail call i32 @llvm.smax.i32(i32 %i1, i32 0)
+  %__b.__a.i.i = select i1 %cmp.i.i, ptr %min, ptr %arrayidx
+  %cmp.i1.i = icmp ugt i32 %i2, 4095
+  %__b.__a.i2.i = select i1 %cmp.i1.i, ptr %max, ptr %__b.__a.i.i
+  %i3 = load i32, ptr %__b.__a.i2.i, align 4
+  ret i32 %i3
+}
+
+declare void @llvm.lifetime.start.p0(i64, ptr )
+declare void @llvm.lifetime.end.p0(i64, ptr)
+declare i32 @llvm.smax.i32(i32, i32)