Skip to content

Commit e15f47f

Browse files
authored
[InstCombine] Don't use dominating conditions to transform sub into xor. (#88566)
Other passes are unable to reverse this transform if we use dominating conditions. Fixes #88239.
1 parent 60b90b5 commit e15f47f

File tree

4 files changed

+19
-10
lines changed

4 files changed

+19
-10
lines changed

llvm/include/llvm/Analysis/SimplifyQuery.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ struct SimplifyQuery {
113113
using namespace PatternMatch;
114114
return match(V, m_Undef());
115115
}
116+
117+
SimplifyQuery getWithoutDomCondCache() const {
118+
SimplifyQuery Copy(*this);
119+
Copy.DC = nullptr;
120+
return Copy;
121+
}
116122
};
117123

118124
} // end namespace llvm

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2281,8 +2281,10 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
22812281
if (match(Op0, m_APInt(Op0C))) {
22822282
if (Op0C->isMask()) {
22832283
// Turn this into a xor if LHS is 2^n-1 and the remaining bits are known
2284-
// zero.
2285-
KnownBits RHSKnown = computeKnownBits(Op1, 0, &I);
2284+
// zero. We don't use information from dominating conditions so this
2285+
// transform is easier to reverse if necessary.
2286+
KnownBits RHSKnown = llvm::computeKnownBits(
2287+
Op1, 0, SQ.getWithInstruction(&I).getWithoutDomCondCache());
22862288
if ((*Op0C | RHSKnown.Zero).isAllOnes())
22872289
return BinaryOperator::CreateXor(Op1, Op0);
22882290
}

llvm/test/Transforms/InstCombine/sub-xor.ll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,15 @@ define <2 x i8> @xor_add_splat_undef(<2 x i8> %x) {
158158
ret <2 x i8> %add
159159
}
160160

161+
; Make sure we don't convert sub to xor using dominating condition. That makes
162+
; it hard for other passe to reverse.
161163
define i32 @xor_dominating_cond(i32 %x) {
162164
; CHECK-LABEL: @xor_dominating_cond(
163165
; CHECK-NEXT: entry:
164166
; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X:%.*]], 256
165167
; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
166168
; CHECK: if.then:
167-
; CHECK-NEXT: [[A:%.*]] = xor i32 [[X]], 255
169+
; CHECK-NEXT: [[A:%.*]] = sub nuw nsw i32 255, [[X]]
168170
; CHECK-NEXT: ret i32 [[A]]
169171
; CHECK: if.end:
170172
; CHECK-NEXT: ret i32 [[X]]

llvm/test/Transforms/PhaseOrdering/X86/pr88239.ll

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,18 @@ define void @foo(ptr noalias noundef %0, ptr noalias noundef %1) optsize {
88
; CHECK-LABEL: define void @foo(
99
; CHECK-SAME: ptr noalias nocapture noundef readonly [[TMP0:%.*]], ptr noalias nocapture noundef writeonly [[TMP1:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
1010
; CHECK-NEXT: vector.ph:
11+
; CHECK-NEXT: [[INVARIANT_GEP:%.*]] = getelementptr i8, ptr [[TMP0]], i64 -28
1112
; CHECK-NEXT: br label [[TMP4:%.*]]
1213
; CHECK: vector.body:
1314
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[TMP2:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[TMP4]] ]
14-
; CHECK-NEXT: [[VEC_IND:%.*]] = phi <8 x i64> [ <i64 0, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7>, [[TMP2]] ], [ [[VEC_IND_NEXT:%.*]], [[TMP4]] ]
15-
; CHECK-NEXT: [[TMP6:%.*]] = and <8 x i64> [[VEC_IND]], <i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295, i64 4294967295>
16-
; CHECK-NEXT: [[TMP3:%.*]] = xor <8 x i64> [[TMP6]], <i64 255, i64 255, i64 255, i64 255, i64 255, i64 255, i64 255, i64 255>
17-
; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], <8 x i64> [[TMP3]]
18-
; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = tail call <8 x i32> @llvm.masked.gather.v8i32.v8p0(<8 x ptr> [[TMP7]], i32 4, <8 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, <8 x i32> poison)
15+
; CHECK-NEXT: [[TMP3:%.*]] = sub nuw nsw i64 255, [[INDVARS_IV]]
16+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[INVARIANT_GEP]], i64 [[TMP3]]
17+
; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = load <8 x i32>, ptr [[GEP]], align 4
1918
; CHECK-NEXT: [[TMP5:%.*]] = add nsw <8 x i32> [[WIDE_MASKED_GATHER]], <i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5>
19+
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <8 x i32> [[TMP5]], <8 x i32> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
2020
; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[INDVARS_IV]]
21-
; CHECK-NEXT: store <8 x i32> [[TMP5]], ptr [[TMP10]], align 4
21+
; CHECK-NEXT: store <8 x i32> [[TMP6]], ptr [[TMP10]], align 4
2222
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 8
23-
; CHECK-NEXT: [[VEC_IND_NEXT]] = add <8 x i64> [[VEC_IND]], <i64 8, i64 8, i64 8, i64 8, i64 8, i64 8, i64 8, i64 8>
2423
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 256
2524
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[MIDDLE_BLOCK:%.*]], label [[TMP4]], !llvm.loop [[LOOP0:![0-9]+]]
2625
; CHECK: middle.block:

0 commit comments

Comments
 (0)