-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[SelectOpt] Support BinOps with SExt operands. #115879
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-backend-aarch64 Author: Florian Hahn (fhahn) ChangesBuilding on top of #115489 Patch is 30.87 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/115879.diff 3 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectOptimize.cpp b/llvm/lib/CodeGen/SelectOptimize.cpp
index 9587534d1170fc..5848e0afb25d98 100644
--- a/llvm/lib/CodeGen/SelectOptimize.cpp
+++ b/llvm/lib/CodeGen/SelectOptimize.cpp
@@ -145,11 +145,20 @@ class SelectOptimizeImpl {
// An Or(zext(i1 X), Y) can also be treated like a select, with condition
// C and values Y|1 and Y.
- Value *X;
- if (PatternMatch::match(
- I, m_c_Or(m_OneUse(m_ZExt(m_Value(X))), m_Value())) &&
- X->getType()->isIntegerTy(1))
- return SelectLike(I);
+ switch (I->getOpcode()) {
+ case Instruction::Add:
+ case Instruction::Or:
+ case Instruction::Sub: {
+ Value *X;
+ if ((PatternMatch::match(I->getOperand(0),
+ m_OneUse(m_ZExtOrSExt(m_Value(X)))) ||
+ PatternMatch::match(I->getOperand(1),
+ m_OneUse(m_ZExtOrSExt(m_Value(X))))) &&
+ X->getType()->isIntegerTy(1))
+ return SelectLike(I);
+ break;
+ }
+ }
return SelectLike(nullptr);
}
@@ -179,10 +188,10 @@ class SelectOptimizeImpl {
if (auto *BO = dyn_cast<BinaryOperator>(I)) {
Value *X;
if (PatternMatch::match(BO->getOperand(0),
- m_OneUse(m_ZExt(m_Value(X)))))
+ m_OneUse(m_ZExtOrSExt(m_Value(X)))))
return X;
if (PatternMatch::match(BO->getOperand(1),
- m_OneUse(m_ZExt(m_Value(X)))))
+ m_OneUse(m_ZExtOrSExt(m_Value(X)))))
return X;
}
@@ -229,10 +238,10 @@ class SelectOptimizeImpl {
if (auto *BO = dyn_cast<BinaryOperator>(I)) {
Value *X;
if (PatternMatch::match(BO->getOperand(0),
- m_OneUse(m_ZExt(m_Value(X)))))
+ m_OneUse(m_ZExtOrSExt(m_Value(X)))))
return BO->getOperand(1);
if (PatternMatch::match(BO->getOperand(1),
- m_OneUse(m_ZExt(m_Value(X)))))
+ m_OneUse(m_ZExtOrSExt(m_Value(X)))))
return BO->getOperand(0);
}
@@ -250,19 +259,22 @@ class SelectOptimizeImpl {
: Scaled64::getZero();
}
- // Or case - add the cost of an extra Or to the cost of the False case.
- if (isa<BinaryOperator>(I))
- if (auto I = dyn_cast<Instruction>(getFalseValue())) {
+ // BinaryOp case - add the cost of an extra BinOp to the cost of the False
+ // case.
+ if (isa<BinaryOperator>(I)) {
+ if (auto OpI = dyn_cast<Instruction>(getFalseValue())) {
auto It = InstCostMap.find(I);
if (It != InstCostMap.end()) {
InstructionCost OrCost = TTI->getArithmeticInstrCost(
- Instruction::Or, I->getType(), TargetTransformInfo::TCK_Latency,
+ I->getOpcode(), OpI->getType(),
+ TargetTransformInfo::TCK_Latency,
{TargetTransformInfo::OK_AnyValue,
TargetTransformInfo::OP_None},
{TTI::OK_UniformConstantValue, TTI::OP_PowerOf2});
return It->second.NonPredCost + Scaled64::get(*OrCost.getValue());
}
}
+ }
return Scaled64::getZero();
}
@@ -548,12 +560,20 @@ getTrueOrFalseValue(SelectOptimizeImpl::SelectLike SI, bool isTrue,
V = (!isTrue ? DefSI->getTrueValue() : DefSI->getFalseValue());
}
- if (isa<BinaryOperator>(SI.getI())) {
- assert(SI.getI()->getOpcode() == Instruction::Or &&
- "Only currently handling Or instructions.");
+ if (auto *BinOp = dyn_cast<BinaryOperator>(SI.getI())) {
+ assert((BinOp->getOpcode() == Instruction::Add ||
+ BinOp->getOpcode() == Instruction::Or ||
+ BinOp->getOpcode() == Instruction::Sub) &&
+ "Only currently handling Add, Or and Sub instructions.");
V = SI.getFalseValue();
- if (isTrue)
- V = IB.CreateOr(V, ConstantInt::get(V->getType(), 1));
+ if (isTrue) {
+ bool HasSExt =
+ (BinOp->getOperand(0) == V && isa<SExtInst>(BinOp->getOperand(1))) ||
+ (BinOp->getOperand(1) == V && isa<SExtInst>(BinOp->getOperand(0)));
+ Constant *CI = HasSExt ? ConstantInt::get(V->getType(), -1)
+ : ConstantInt::get(V->getType(), 1);
+ V = IB.CreateBinOp(BinOp->getOpcode(), V, CI);
+ }
}
assert(V && "Failed to get select true/false value");
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index 71f9bbbbc35041..75eea291896ef7 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -4678,14 +4678,20 @@ AArch64TTIImpl::getScalingFactorCost(Type *Ty, GlobalValue *BaseGV,
}
bool AArch64TTIImpl::shouldTreatInstructionLikeSelect(const Instruction *I) {
- // For the binary operators (e.g. or) we need to be more careful than
- // selects, here we only transform them if they are already at a natural
- // break point in the code - the end of a block with an unconditional
- // terminator.
- if (EnableOrLikeSelectOpt && I->getOpcode() == Instruction::Or &&
- isa<BranchInst>(I->getNextNode()) &&
- cast<BranchInst>(I->getNextNode())->isUnconditional())
- return true;
+ if (EnableOrLikeSelectOpt) {
+ // For the binary operators (e.g. or) we need to be more careful than
+ // selects, here we only transform them if they are already at a natural
+ // break point in the code - the end of a block with an unconditional
+ // terminator.
+ if (I->getOpcode() == Instruction::Or &&
+ isa<BranchInst>(I->getNextNode()) &&
+ cast<BranchInst>(I->getNextNode())->isUnconditional())
+ return true;
+
+ if (I->getOpcode() == Instruction::Add ||
+ I->getOpcode() == Instruction::Sub)
+ return true;
+ }
return BaseT::shouldTreatInstructionLikeSelect(I);
}
diff --git a/llvm/test/CodeGen/AArch64/selectopt-cast.ll b/llvm/test/CodeGen/AArch64/selectopt-cast.ll
index b1804a02ec1c82..ce137443e93994 100644
--- a/llvm/test/CodeGen/AArch64/selectopt-cast.ll
+++ b/llvm/test/CodeGen/AArch64/selectopt-cast.ll
@@ -7,16 +7,22 @@ define void @test_add_zext(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.star
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ]
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
+; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
+; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
; CHECK-NEXT: [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
; CHECK-NEXT: [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
; CHECK-NEXT: [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
; CHECK-NEXT: [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
; CHECK-NEXT: [[DEC:%.*]] = zext i1 [[CMP3]] to i64
-; CHECK-NEXT: [[J_NEXT]] = add nsw i64 [[J]], [[DEC]]
+; CHECK-NEXT: [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[J]], 1
+; CHECK-NEXT: br i1 [[CMP3_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE:%.*]]
+; CHECK: select.false:
+; CHECK-NEXT: br label [[SELECT_END]]
+; CHECK: select.end:
+; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[TMP0]], [[LOOP]] ], [ [[J]], [[SELECT_FALSE]] ]
; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
; CHECK-NEXT: store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
@@ -54,9 +60,9 @@ define void @test_add_zext_not(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ]
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
+; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
+; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
; CHECK-NEXT: [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
; CHECK-NEXT: [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
; CHECK-NEXT: [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
@@ -64,7 +70,13 @@ define void @test_add_zext_not(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
; CHECK-NEXT: [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true
; CHECK-NEXT: [[DEC:%.*]] = zext i1 [[NOT_CMP3]] to i64
-; CHECK-NEXT: [[J_NEXT]] = add nsw i64 [[J]], [[DEC]]
+; CHECK-NEXT: [[NOT_CMP3_FROZEN:%.*]] = freeze i1 [[NOT_CMP3]]
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[J]], 1
+; CHECK-NEXT: br i1 [[NOT_CMP3_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE:%.*]]
+; CHECK: select.false:
+; CHECK-NEXT: br label [[SELECT_END]]
+; CHECK: select.end:
+; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[TMP0]], [[LOOP]] ], [ [[J]], [[SELECT_FALSE]] ]
; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
; CHECK-NEXT: store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
@@ -102,16 +114,22 @@ define void @test_add_sext(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.star
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ]
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
+; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
+; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
; CHECK-NEXT: [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
; CHECK-NEXT: [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
; CHECK-NEXT: [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
; CHECK-NEXT: [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
; CHECK-NEXT: [[DEC:%.*]] = sext i1 [[CMP3]] to i64
-; CHECK-NEXT: [[J_NEXT]] = add nsw i64 [[J]], [[DEC]]
+; CHECK-NEXT: [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[J]], -1
+; CHECK-NEXT: br i1 [[CMP3_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE:%.*]]
+; CHECK: select.false:
+; CHECK-NEXT: br label [[SELECT_END]]
+; CHECK: select.end:
+; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[TMP0]], [[LOOP]] ], [ [[J]], [[SELECT_FALSE]] ]
; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
; CHECK-NEXT: store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
@@ -149,9 +167,9 @@ define void @test_add_sext_not(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ]
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
+; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
+; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
; CHECK-NEXT: [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
; CHECK-NEXT: [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
; CHECK-NEXT: [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
@@ -159,7 +177,13 @@ define void @test_add_sext_not(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
; CHECK-NEXT: [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true
; CHECK-NEXT: [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64
-; CHECK-NEXT: [[J_NEXT]] = add nsw i64 [[J]], [[DEC]]
+; CHECK-NEXT: [[NOT_CMP3_FROZEN:%.*]] = freeze i1 [[NOT_CMP3]]
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[J]], -1
+; CHECK-NEXT: br i1 [[NOT_CMP3_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE:%.*]]
+; CHECK: select.false:
+; CHECK-NEXT: br label [[SELECT_END]]
+; CHECK: select.end:
+; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[TMP0]], [[LOOP]] ], [ [[J]], [[SELECT_FALSE]] ]
; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
; CHECK-NEXT: store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
@@ -198,9 +222,9 @@ define void @test_add_sext_not_and_regular_select(ptr %dst, ptr %src, i64 %j.sta
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ]
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END1:%.*]] ]
+; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END1]] ]
+; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END1]] ]
; CHECK-NEXT: [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
; CHECK-NEXT: [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
; CHECK-NEXT: [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
@@ -208,8 +232,19 @@ define void @test_add_sext_not_and_regular_select(ptr %dst, ptr %src, i64 %j.sta
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
; CHECK-NEXT: [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true
; CHECK-NEXT: [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64
-; CHECK-NEXT: [[J_NEXT]] = add nsw i64 [[J]], [[DEC]]
-; CHECK-NEXT: [[SINK:%.*]] = select i1 [[CMP3]], ptr [[L_I]], ptr [[L_J]]
+; CHECK-NEXT: [[NOT_CMP3_FROZEN:%.*]] = freeze i1 [[NOT_CMP3]]
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[J]], -1
+; CHECK-NEXT: br i1 [[NOT_CMP3_FROZEN]], label [[SELECT_END:%.*]], label [[SELECT_FALSE:%.*]]
+; CHECK: select.false:
+; CHECK-NEXT: br label [[SELECT_END]]
+; CHECK: select.end:
+; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[TMP0]], [[LOOP]] ], [ [[J]], [[SELECT_FALSE]] ]
+; CHECK-NEXT: [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
+; CHECK-NEXT: br i1 [[CMP3_FROZEN]], label [[SELECT_END1]], label [[SELECT_FALSE2:%.*]]
+; CHECK: select.false2:
+; CHECK-NEXT: br label [[SELECT_END1]]
+; CHECK: select.end1:
+; CHECK-NEXT: [[SINK:%.*]] = phi ptr [ [[L_I]], [[SELECT_END]] ], [ [[L_J]], [[SELECT_FALSE2]] ]
; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
; CHECK-NEXT: store ptr [[SINK]], ptr [[GEP_DST]], align 8
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
@@ -249,9 +284,9 @@ define void @test_add_sext_not_and_regular_select2(ptr %dst, ptr %src, i64 %j.st
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ]
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END1:%.*]] ]
+; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END1]] ]
+; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END1]] ]
; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX1]], align 8
; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
@@ -261,10 +296,21 @@ define void @test_add_sext_not_and_regular_select2(ptr %dst, ptr %src, i64 %j.st
; CHECK-NEXT: [[ARRAYIDX1_I:%.*]] = getelementptr inbounds i64, ptr [[TMP1]], i64 [[P]]
; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[ARRAYIDX1_I]], align 8
; CHECK-NEXT: [[CMP3:%.*]] = icmp slt i64 [[TMP2]], [[TMP3]]
-; CHECK-NEXT: [[DOTSINK:%.*]] = select i1 [[CMP3]], ptr [[TMP0]], ptr [[TMP1]]
+; CHECK-NEXT: [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
+; CHECK-NEXT: br i1 [[CMP3_FROZEN]], label [[SELECT_END:%.*]], label [[SELECT_FALSE:%.*]]
+; CHECK: select.false:
+; CHECK-NEXT: br label [[SELECT_END]]
+; CHECK: select.end:
+; CHECK-NEXT: [[DOTSINK:%.*]] = phi ptr [ [[TMP0]], [[LOOP]] ], [ [[TMP1]], [[SELECT_FALSE]] ]
; CHECK-NEXT: [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true
; CHECK-NEXT: [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64
-; CHECK-NEXT: [[J_NEXT]] = add nsw i64 [[J]], [[DEC]]
+; CHECK-NEXT: [[NOT_CMP3_FROZEN:%.*]] = freeze i1 [[NOT_CMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[J]], -1
+; CHECK-NEXT: br i1 [[NOT_CMP3_FROZEN]], label [[SELECT_END1]], label [[SELECT_FALSE2:%.*]]
+; CHECK: select.false2:
+; CHECK-NEXT: br label [[SELECT_END1]]
+; CHECK: select.end1:
+; CHECK-NEXT: [[J_NEXT]] = phi i64 [ [[TMP5]], [[SELECT_END]] ], [ [[J]], [[SELECT_FALSE2]] ]
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
; CHECK-NEXT: store ptr [[DOTSINK]], ptr [[TMP4]], align 8
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
@@ -308,16 +354,22 @@ define void @test_sub_zext(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.star
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ]
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
+; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
+; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
; CHECK-NEXT: [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
; CHECK-NEXT: [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
; CHECK-NEXT: [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
; CHECK-NEXT: [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
; CHECK-NEXT: [[DEC:%.*]] = zext i1 [[CMP3]] to i64
-; CHECK-NEXT: [[J_NEXT]] = sub nsw i64 [[J]], [[DEC]]
+; CHECK-NEXT: [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
+; CHECK-NEXT: [[TMP0:%.*]] = sub i64 [[J]], 1
+; CHECK-NEXT: br i1 [[CMP3_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE:%.*]]
+; CHECK: select.false:
+; CHECK-...
[truncated]
|
|
Looks good; the only question is whether we want to add it before or after #115745 (assuming it gets accepted) |
|
Same as #115489, LGTM as well. |
|
Ping |
Building on top of llvm#115489 extend support for binops with SExt operand.
b67a1c3 to
b7cc95e
Compare
|
Updated on top of current |
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Building on top of llvm#115489 extend support for binops with SExt operand. PR: llvm#115879 (cherry picked from commit c1f5937)
Building on top of #115489
extend support for binops with SExt operand.