Skip to content

Commit 2e60048

Browse files
authored
[InstCombine] Fold zext(X) + C2 pred C -> X + C3 pred C4 (#110511)
Motivating case from https://github.com/torvalds/linux/blob/9852d85ec9d492ebef56dc5f229416c925758edc/drivers/gpu/drm/drm_edid.c#L5238-L5240: ``` define i1 @src(i8 noundef %v13) { entry: %conv1 = zext i8 %v13 to i32 %add = add nsw i32 %conv1, -4 %cmp = icmp ult i32 %add, 3 %cmp4 = icmp slt i8 %v13, 4 %cond = select i1 %cmp4, i1 true, i1 %cmp ret i1 %cond } define i1 @tgt(i8 noundef %v13) { entry: %cmp4 = icmp slt i8 %v13, 7 ret i1 %cmp4 } ```
1 parent 4872ecf commit 2e60048

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3183,6 +3183,30 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
31833183
Builder.CreateAdd(X, ConstantInt::get(Ty, *C2 - C - 1)),
31843184
ConstantInt::get(Ty, ~C));
31853185

3186+
// zext(V) + C2 pred C -> V + C3 pred' C4
3187+
Value *V;
3188+
if (match(X, m_ZExt(m_Value(V)))) {
3189+
Type *NewCmpTy = V->getType();
3190+
unsigned CmpBW = Ty->getScalarSizeInBits();
3191+
unsigned NewCmpBW = NewCmpTy->getScalarSizeInBits();
3192+
if (shouldChangeType(Ty, NewCmpTy)) {
3193+
if (CR.getActiveBits() <= NewCmpBW) {
3194+
ConstantRange SrcCR = CR.truncate(NewCmpBW);
3195+
CmpInst::Predicate EquivPred;
3196+
APInt EquivInt;
3197+
APInt EquivOffset;
3198+
3199+
SrcCR.getEquivalentICmp(EquivPred, EquivInt, EquivOffset);
3200+
return new ICmpInst(
3201+
EquivPred,
3202+
EquivOffset.isZero()
3203+
? V
3204+
: Builder.CreateAdd(V, ConstantInt::get(NewCmpTy, EquivOffset)),
3205+
ConstantInt::get(NewCmpTy, EquivInt));
3206+
}
3207+
}
3208+
}
3209+
31863210
return nullptr;
31873211
}
31883212

llvm/test/Transforms/InstCombine/icmp-add.ll

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3183,3 +3183,109 @@ define i1 @icmp_of_ucmp_plus_const_with_const(i32 %x, i32 %y) {
31833183
%cmp2 = icmp ult i8 %add, 2
31843184
ret i1 %cmp2
31853185
}
3186+
3187+
define i1 @zext_range_check_ult(i8 %x) {
3188+
; CHECK-LABEL: @zext_range_check_ult(
3189+
; CHECK-NEXT: entry:
3190+
; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[X:%.*]], -4
3191+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[TMP0]], 3
3192+
; CHECK-NEXT: ret i1 [[CMP]]
3193+
;
3194+
entry:
3195+
%conv = zext i8 %x to i32
3196+
%add = add i32 %conv, -4
3197+
%cmp = icmp ult i32 %add, 3
3198+
ret i1 %cmp
3199+
}
3200+
3201+
; TODO: should be canonicalized to (x - 4) u> 2
3202+
define i1 @zext_range_check_ugt(i8 %x) {
3203+
; CHECK-LABEL: @zext_range_check_ugt(
3204+
; CHECK-NEXT: entry:
3205+
; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[X:%.*]] to i32
3206+
; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[CONV]], -7
3207+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP0]], -3
3208+
; CHECK-NEXT: ret i1 [[CMP]]
3209+
;
3210+
entry:
3211+
%conv = zext i8 %x to i32
3212+
%add = add i32 %conv, -4
3213+
%cmp = icmp ugt i32 %add, 2
3214+
ret i1 %cmp
3215+
}
3216+
3217+
; TODO: should be canonicalized to (x - 4) u> 2
3218+
define i1 @zext_range_check_ult_alter(i8 %x) {
3219+
; CHECK-LABEL: @zext_range_check_ult_alter(
3220+
; CHECK-NEXT: entry:
3221+
; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[X:%.*]] to i32
3222+
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], -7
3223+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], -3
3224+
; CHECK-NEXT: ret i1 [[CMP]]
3225+
;
3226+
entry:
3227+
%conv = zext i8 %x to i32
3228+
%add = add i32 %conv, -7
3229+
%cmp = icmp ult i32 %add, -3
3230+
ret i1 %cmp
3231+
}
3232+
3233+
define i1 @zext_range_check_mergable(i8 %x) {
3234+
; CHECK-LABEL: @zext_range_check_mergable(
3235+
; CHECK-NEXT: [[COND:%.*]] = icmp slt i8 [[X:%.*]], 7
3236+
; CHECK-NEXT: ret i1 [[COND]]
3237+
;
3238+
%conv = zext i8 %x to i32
3239+
%add = add nsw i32 %conv, -4
3240+
%cmp1 = icmp ult i32 %add, 3
3241+
%cmp2 = icmp slt i8 %x, 4
3242+
%cond = select i1 %cmp2, i1 true, i1 %cmp1
3243+
ret i1 %cond
3244+
}
3245+
3246+
; Negative tests
3247+
3248+
define i1 @sext_range_check_ult(i8 %x) {
3249+
; CHECK-LABEL: @sext_range_check_ult(
3250+
; CHECK-NEXT: entry:
3251+
; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[X:%.*]] to i32
3252+
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], -4
3253+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 3
3254+
; CHECK-NEXT: ret i1 [[CMP]]
3255+
;
3256+
entry:
3257+
%conv = sext i8 %x to i32
3258+
%add = add i32 %conv, -4
3259+
%cmp = icmp ult i32 %add, 3
3260+
ret i1 %cmp
3261+
}
3262+
3263+
define i1 @zext_range_check_ult_illegal_type(i7 %x) {
3264+
; CHECK-LABEL: @zext_range_check_ult_illegal_type(
3265+
; CHECK-NEXT: entry:
3266+
; CHECK-NEXT: [[CONV:%.*]] = zext i7 [[X:%.*]] to i32
3267+
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], -4
3268+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 3
3269+
; CHECK-NEXT: ret i1 [[CMP]]
3270+
;
3271+
entry:
3272+
%conv = zext i7 %x to i32
3273+
%add = add i32 %conv, -4
3274+
%cmp = icmp ult i32 %add, 3
3275+
ret i1 %cmp
3276+
}
3277+
3278+
define i1 @zext_range_check_ult_range_check_failure(i8 %x) {
3279+
; CHECK-LABEL: @zext_range_check_ult_range_check_failure(
3280+
; CHECK-NEXT: entry:
3281+
; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[X:%.*]] to i32
3282+
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], -4
3283+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 253
3284+
; CHECK-NEXT: ret i1 [[CMP]]
3285+
;
3286+
entry:
3287+
%conv = zext i8 %x to i32
3288+
%add = add i32 %conv, -4
3289+
%cmp = icmp ult i32 %add, 253
3290+
ret i1 %cmp
3291+
}

0 commit comments

Comments
 (0)