Skip to content

Commit 7015a5c

Browse files
committed
[InstCombine] conditional sign-extend of high-bit-extract: 'or' pattern.
In this pattern, all the "magic" bits that we'd `add` are all high sign bits, and in the value we'd be adding to they are all unset, not unexpectedly, so we can have an `or` there: https://rise4fun.com/Alive/ups It is possible that `haveNoCommonBitsSet()` should be taught about this pattern so that we never have an `add` variant, but the reasoning would need to be recursive (because of that `select`), so i'm not really sure that would be worth it just yet. llvm-svn: 375378
1 parent f7aec25 commit 7015a5c

File tree

4 files changed

+26
-21
lines changed

4 files changed

+26
-21
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,10 +1097,11 @@ static Instruction *foldToUnsignedSaturatedAdd(BinaryOperator &I) {
10971097
return nullptr;
10981098
}
10991099

1100-
static Instruction *
1101-
canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(
1102-
BinaryOperator &I, InstCombiner::BuilderTy &Builder) {
1100+
Instruction *
1101+
InstCombiner::canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(
1102+
BinaryOperator &I) {
11031103
assert((I.getOpcode() == Instruction::Add ||
1104+
I.getOpcode() == Instruction::Or ||
11041105
I.getOpcode() == Instruction::Sub) &&
11051106
"Expecting add/sub instruction");
11061107

@@ -1114,7 +1115,7 @@ canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(
11141115
m_Value(Select))))
11151116
return nullptr;
11161117

1117-
// `add` is commutative; but for `sub`, "select" *must* be on RHS.
1118+
// `add`/`or` is commutative; but for `sub`, "select" *must* be on RHS.
11181119
if (I.getOpcode() == Instruction::Sub && I.getOperand(1) != Select)
11191120
return nullptr;
11201121

@@ -1140,13 +1141,13 @@ canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(
11401141
X->getType()->getScalarSizeInBits()))))
11411142
return nullptr;
11421143

1143-
// Sign-extending value can be sign-extended itself if we `add` it,
1144-
// or zero-extended if we `sub`tract it.
1144+
// Sign-extending value can be zero-extended if we `sub`tract it,
1145+
// or sign-extended otherwise.
11451146
auto SkipExtInMagic = [&I](Value *&V) {
1146-
if (I.getOpcode() == Instruction::Add)
1147-
match(V, m_SExtOrSelf(m_Value(V)));
1148-
else
1147+
if (I.getOpcode() == Instruction::Sub)
11491148
match(V, m_ZExtOrSelf(m_Value(V)));
1149+
else
1150+
match(V, m_SExtOrSelf(m_Value(V)));
11501151
};
11511152

11521153
// Now, finally validate the sign-extending magic.
@@ -1169,7 +1170,7 @@ canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(
11691170
if (!ShouldSignext)
11701171
std::swap(SignExtendingValue, Zero);
11711172

1172-
// If we should not perform sign-extension then we must add/subtract zero.
1173+
// If we should not perform sign-extension then we must add/or/subtract zero.
11731174
if (!match(Zero, m_Zero()))
11741175
return nullptr;
11751176
// Otherwise, it should be some constant, left-shifted by the same NBits we
@@ -1181,10 +1182,10 @@ canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(
11811182
m_Shl(m_Constant(SignExtendingValueBaseConstant),
11821183
m_ZExtOrSelf(m_Specific(NBits)))))
11831184
return nullptr;
1184-
// If we `add`, then the constant should be all-ones, else it should be one.
1185-
if (I.getOpcode() == Instruction::Add
1186-
? !match(SignExtendingValueBaseConstant, m_AllOnes())
1187-
: !match(SignExtendingValueBaseConstant, m_One()))
1185+
// If we `sub`, then the constant should be one, else it should be all-ones.
1186+
if (I.getOpcode() == Instruction::Sub
1187+
? !match(SignExtendingValueBaseConstant, m_One())
1188+
: !match(SignExtendingValueBaseConstant, m_AllOnes()))
11881189
return nullptr;
11891190

11901191
auto *NewAShr = BinaryOperator::CreateAShr(X, LowBitsToSkip,
@@ -1403,8 +1404,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
14031404
return V;
14041405

14051406
if (Instruction *V =
1406-
canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(
1407-
I, Builder))
1407+
canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(I))
14081408
return V;
14091409

14101410
if (Instruction *SatAdd = foldToUnsignedSaturatedAdd(I))
@@ -2006,8 +2006,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
20062006
}
20072007

20082008
if (Instruction *V =
2009-
canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(
2010-
I, Builder))
2009+
canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(I))
20112010
return V;
20122011

20132012
if (Instruction *Ext = narrowMathIfNoOverflow(I))

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2725,6 +2725,10 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
27252725
}
27262726
}
27272727

2728+
if (Instruction *V =
2729+
canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(I))
2730+
return V;
2731+
27282732
return nullptr;
27292733
}
27302734

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,8 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner
393393
Value *reassociateShiftAmtsOfTwoSameDirectionShifts(
394394
BinaryOperator *Sh0, const SimplifyQuery &SQ,
395395
bool AnalyzeForSignBitExtraction = false);
396+
Instruction *canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(
397+
BinaryOperator &I);
396398
Instruction *foldVariableSignZeroExtensionOfVariableHighBitExtract(
397399
BinaryOperator &OldAShr);
398400
Instruction *visitAShr(BinaryOperator &I);

llvm/test/Transforms/InstCombine/conditional-variable-length-signext-after-high-bit-extract.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ define i32 @t0_notrunc_or(i32 %data, i32 %nbits) {
5757
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
5858
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
5959
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
60-
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = or i32 [[HIGH_BITS_EXTRACTED]], [[MAGIC]]
60+
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
6161
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
6262
;
6363
%low_bits_to_skip = sub i32 32, %nbits
@@ -152,14 +152,14 @@ define i32 @t2_trunc_or(i64 %data, i32 %nbits) {
152152
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = trunc i64 [[HIGH_BITS_EXTRACTED_WIDE]] to i32
153153
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i64 [[DATA]], 0
154154
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
155-
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
156155
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
157156
; CHECK-NEXT: call void @use64(i64 [[LOW_BITS_TO_SKIP_WIDE]])
158157
; CHECK-NEXT: call void @use64(i64 [[HIGH_BITS_EXTRACTED_WIDE]])
159158
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
160159
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
161160
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
162-
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = or i32 [[MAGIC]], [[HIGH_BITS_EXTRACTED]]
161+
; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[LOW_BITS_TO_SKIP_WIDE]]
162+
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
163163
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
164164
;
165165
%low_bits_to_skip = sub i32 64, %nbits

0 commit comments

Comments
 (0)