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
[InstCombine] Fix worklist management in select fold #77738
Conversation
`InstCombine` uses `Worklist` to manage change history. `setOperand`, which was previously used to change the `Select` Instruction, does not, so it is `run` twice, which causes an `LLVM ERROR`. This problem is resolved by changing `setOperand` to `replaceOperand` as the change history will be registered in the Worklist.
@llvm/pr-subscribers-llvm-transforms Author: hanbeom (ParkHanbum) Changes
This problem is resolved by changing Full diff: https://github.com/llvm/llvm-project/pull/77738.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 2dda46986f0fd0..1aa47b2ccfd82b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1703,11 +1703,11 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
if (CmpRHS != CmpLHS && isa<Constant>(CmpRHS) && !isa<Constant>(CmpLHS)) {
if (CmpLHS == TrueVal && Pred == ICmpInst::ICMP_EQ) {
// Transform (X == C) ? X : Y -> (X == C) ? C : Y
- SI.setOperand(1, CmpRHS);
+ replaceOperand(SI, 1, CmpRHS);
Changed = true;
} else if (CmpLHS == FalseVal && Pred == ICmpInst::ICMP_NE) {
// Transform (X != C) ? Y : X -> (X != C) ? Y : C
- SI.setOperand(2, CmpRHS);
+ replaceOperand(SI, 2, CmpRHS);
Changed = true;
}
}
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 7583a75385a769..5687371b4e1dd2 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -3646,3 +3646,17 @@ loop:
exit:
ret i32 %rem
}
+
+; (X == C) ? X : Y -> (X == C) ? C : Y
+; Fixed #77553
+define i32 @src_select_xxory_eq0_xorxy_y(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xxory_eq0_xorxy_y(
+; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 0, i32 [[Y]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %xor = xor i32 %x, %y
+ %xor0 = icmp eq i32 %xor, 0
+ %cond = select i1 %xor0, i32 %xor, i32 %y
+ ret i32 %cond
+}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I tested it on my local machine.
`InstCombine` uses `Worklist` to manage change history. `setOperand`, which was previously used to change the `Select` Instruction, does not, so it is `run` twice, which causes an `LLVM ERROR`. This problem is resolved by changing `setOperand` to `replaceOperand` as the change history will be registered in the Worklist. Fixes llvm#77553.
InstCombine
usesWorklist
to manage change history.setOperand
, which was previously used to change theSelect
Instruction, does not, so it isrun
twice, which causes anLLVM ERROR
.This problem is resolved by changing
setOperand
toreplaceOperand
as the change history will be registered in the Worklist.Fixes #77553.