Skip to content

Commit 897c985

Browse files
committed
[InstCombine] Canonicalize SPF to abs intrinsic
This patch enables canonicalization of SPF_ABS and SPF_ABS to the abs intrinsic. This is a recommit, the original try was 05d4c4e, but it was reverted due to an apparent miscompile, which since then has just been fixed by the previous commit. Differential Revision: https://reviews.llvm.org/D87188
1 parent e9289dc commit 897c985

File tree

12 files changed

+361
-638
lines changed

12 files changed

+361
-638
lines changed

clang/test/CodeGen/builtins-wasm.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -384,26 +384,20 @@ u8x16 sub_saturate_u_i8x16(u8x16 x, u8x16 y) {
384384

385385
i8x16 abs_i8x16(i8x16 v) {
386386
return __builtin_wasm_abs_i8x16(v);
387-
// WEBASSEMBLY: %neg = sub <16 x i8> zeroinitializer, %v
388-
// WEBASSEMBLY: %abscond = icmp slt <16 x i8> %v, zeroinitializer
389-
// WEBASSEMBLY: %abs = select <16 x i1> %abscond, <16 x i8> %neg, <16 x i8> %v
390-
// WEBASSEMBLY: ret <16 x i8> %abs
387+
// WEBASSEMBLY: call <16 x i8> @llvm.abs.v16i8(<16 x i8> %v, i1 false)
388+
// WEBASSEMBLY-NEXT: ret
391389
}
392390

393391
i16x8 abs_i16x8(i16x8 v) {
394392
return __builtin_wasm_abs_i16x8(v);
395-
// WEBASSEMBLY: %neg = sub <8 x i16> zeroinitializer, %v
396-
// WEBASSEMBLY: %abscond = icmp slt <8 x i16> %v, zeroinitializer
397-
// WEBASSEMBLY: %abs = select <8 x i1> %abscond, <8 x i16> %neg, <8 x i16> %v
398-
// WEBASSEMBLY: ret <8 x i16> %abs
393+
// WEBASSEMBLY: call <8 x i16> @llvm.abs.v8i16(<8 x i16> %v, i1 false)
394+
// WEBASSEMBLY-NEXT: ret
399395
}
400396

401397
i32x4 abs_i32x4(i32x4 v) {
402398
return __builtin_wasm_abs_i32x4(v);
403-
// WEBASSEMBLY: %neg = sub <4 x i32> zeroinitializer, %v
404-
// WEBASSEMBLY: %abscond = icmp slt <4 x i32> %v, zeroinitializer
405-
// WEBASSEMBLY: %abs = select <4 x i1> %abscond, <4 x i32> %neg, <4 x i32> %v
406-
// WEBASSEMBLY: ret <4 x i32> %abs
399+
// WEBASSEMBLY: call <4 x i32> @llvm.abs.v4i32(<4 x i32> %v, i1 false)
400+
// WEBASSEMBLY-NEXT: ret
407401
}
408402

409403
i8x16 min_s_i8x16(i8x16 x, i8x16 y) {

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 9 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,89 +1047,28 @@ static Instruction *canonicalizeMinMaxWithConstant(SelectInst &Sel,
10471047
return &Sel;
10481048
}
10491049

1050-
/// There are many select variants for each of ABS/NABS.
1051-
/// In matchSelectPattern(), there are different compare constants, compare
1052-
/// predicates/operands and select operands.
1053-
/// In isKnownNegation(), there are different formats of negated operands.
1054-
/// Canonicalize all these variants to 1 pattern.
1055-
/// This makes CSE more likely.
10561050
static Instruction *canonicalizeAbsNabs(SelectInst &Sel, ICmpInst &Cmp,
10571051
InstCombinerImpl &IC) {
10581052
if (!Cmp.hasOneUse() || !isa<Constant>(Cmp.getOperand(1)))
10591053
return nullptr;
10601054

1061-
// Choose a sign-bit check for the compare (likely simpler for codegen).
1062-
// ABS: (X <s 0) ? -X : X
1063-
// NABS: (X <s 0) ? X : -X
10641055
Value *LHS, *RHS;
10651056
SelectPatternFlavor SPF = matchSelectPattern(&Sel, LHS, RHS).Flavor;
10661057
if (SPF != SelectPatternFlavor::SPF_ABS &&
10671058
SPF != SelectPatternFlavor::SPF_NABS)
10681059
return nullptr;
10691060

1070-
Value *TVal = Sel.getTrueValue();
1071-
Value *FVal = Sel.getFalseValue();
1072-
assert(isKnownNegation(TVal, FVal) &&
1073-
"Unexpected result from matchSelectPattern");
1074-
1075-
// The compare may use the negated abs()/nabs() operand, or it may use
1076-
// negation in non-canonical form such as: sub A, B.
1077-
bool CmpUsesNegatedOp = match(Cmp.getOperand(0), m_Neg(m_Specific(TVal))) ||
1078-
match(Cmp.getOperand(0), m_Neg(m_Specific(FVal)));
1079-
1080-
bool CmpCanonicalized = !CmpUsesNegatedOp &&
1081-
match(Cmp.getOperand(1), m_ZeroInt()) &&
1082-
Cmp.getPredicate() == ICmpInst::ICMP_SLT;
1083-
bool RHSCanonicalized = match(RHS, m_Neg(m_Specific(LHS)));
1084-
1085-
// Is this already canonical?
1086-
if (CmpCanonicalized && RHSCanonicalized)
1087-
return nullptr;
1088-
1089-
// If RHS is not canonical but is used by other instructions, don't
1090-
// canonicalize it and potentially increase the instruction count.
1091-
if (!RHSCanonicalized)
1092-
if (!(RHS->hasOneUse() || (RHS->hasNUses(2) && CmpUsesNegatedOp)))
1093-
return nullptr;
1061+
bool IntMinIsPoison = match(RHS, m_NSWNeg(m_Specific(LHS)));
1062+
Constant *IntMinIsPoisonC =
1063+
ConstantInt::get(Type::getInt1Ty(Sel.getContext()), IntMinIsPoison);
1064+
Instruction *Abs =
1065+
IC.Builder.CreateBinaryIntrinsic(Intrinsic::abs, LHS, IntMinIsPoisonC);
10941066

1095-
// Create the canonical compare: icmp slt LHS 0.
1096-
if (!CmpCanonicalized) {
1097-
Cmp.setPredicate(ICmpInst::ICMP_SLT);
1098-
Cmp.setOperand(1, ConstantInt::getNullValue(Cmp.getOperand(0)->getType()));
1099-
if (CmpUsesNegatedOp)
1100-
Cmp.setOperand(0, LHS);
1101-
}
1102-
1103-
// Create the canonical RHS: RHS = sub (0, LHS).
1104-
if (!RHSCanonicalized) {
1105-
assert(RHS->hasOneUse() && "RHS use number is not right");
1106-
RHS = IC.Builder.CreateNeg(LHS);
1107-
if (TVal == LHS) {
1108-
// Replace false value.
1109-
IC.replaceOperand(Sel, 2, RHS);
1110-
FVal = RHS;
1111-
} else {
1112-
// Replace true value.
1113-
IC.replaceOperand(Sel, 1, RHS);
1114-
TVal = RHS;
1115-
}
1116-
}
1067+
if (SPF == SelectPatternFlavor::SPF_NABS)
1068+
return IntMinIsPoison ? BinaryOperator::CreateNSWNeg(Abs)
1069+
: BinaryOperator::CreateNeg(Abs);
11171070

1118-
// If the select operands do not change, we're done.
1119-
if (SPF == SelectPatternFlavor::SPF_NABS) {
1120-
if (TVal == LHS)
1121-
return &Sel;
1122-
assert(FVal == LHS && "Unexpected results from matchSelectPattern");
1123-
} else {
1124-
if (FVal == LHS)
1125-
return &Sel;
1126-
assert(TVal == LHS && "Unexpected results from matchSelectPattern");
1127-
}
1128-
1129-
// We are swapping the select operands, so swap the metadata too.
1130-
Sel.swapValues();
1131-
Sel.swapProfMetadata();
1132-
return &Sel;
1071+
return IC.replaceInstUsesWith(Sel, Abs);
11331072
}
11341073

11351074
/// If we have a select with an equality comparison, then we know the value in

0 commit comments

Comments
 (0)