[Optimizer] Constant-fold cc::IfOp successor regions and invocation bounds#4191
[Optimizer] Constant-fold cc::IfOp successor regions and invocation bounds#4191sanarang-nv wants to merge 3 commits intoNVIDIA:mainfrom
Conversation
Command Bot: Processing... |
|
Seems like there are some build failures, please try to build cudaq locally using |
Signed-off-by: Samarth Narang <sanarang@nvidia.com>
@sacpis, thanks. I wasn't able to setup the devcontainer earlier, but it went through and I was able to run |
Command Bot: Processing... |
|
CUDA Quantum Docs Bot: A preview of the documentation can be found here. |
|
I know folding IfOp was already done at one point. Let me see if I can find it... |
OK. There is a bit of code in the
Nevermind, this does not really fold the cc.if. |
schweitzpgi
left a comment
There was a problem hiding this comment.
I want to check a few more things before approving this...
| %c42 = arith.constant 42 : i32 | ||
| cc.if (%true) { | ||
| func.call @use_i32(%c42) : (i32) -> () | ||
| cc.continue |
There was a problem hiding this comment.
| cc.continue |
This continue isn't necessary.
schweitzpgi
left a comment
There was a problem hiding this comment.
Can you clarify what this is really affecting? To wit, for this input:
func.func private @use_i32(i32)
func.func @sink_into_true_branch() {
%true = arith.constant true
%c42 = arith.constant 42 : i32
%c43 = arith.constant 43 : i32
cc.if (%true) {
func.call @use_i32(%c42) : (i32) -> ()
} else {
func.call @use_i32(%c43) : (i32) -> ()
}
return
}The command line cudaq-opt -control-flow-sink test.qke without these changes will already produce.
module {
func.func private @use_i32(i32)
func.func @sink_into_true_branch() {
%true = arith.constant true
cc.if(%true) {
%c42_i32 = arith.constant 42 : i32
func.call @use_i32(%c42_i32) : (i32) -> ()
} else {
%c43_i32 = arith.constant 43 : i32
func.call @use_i32(%c43_i32) : (i32) -> ()
}
return
}
}which suggests that this pass doesn't really exercise the changes.
Furthermore, the cc.if op is not folded in any way. If it neither removed nor is the else branch eliminated before or after these changes.
With the changes yields:
module {
func.func private @use_i32(i32)
func.func @sink_into_true_branch() {
%true = arith.constant true
cc.if(%true) {
%c42_i32 = arith.constant 42 : i32
func.call @use_i32(%c42_i32) : (i32) -> ()
} else {
%c43_i32 = arith.constant 43 : i32
func.call @use_i32(%c43_i32) : (i32) -> ()
}
return
}
}which is the exact same IR.
**What does this PR implement? **
This PR applies two (similar) flavors of constant folding on the
IfOp:cc::IfOp::getSuccessorRegions: when the condition is a compile-time constant, only the live region is returned as a successor.cc::IfOp::getRegionInvocationBounds: when the condition is constant, the live region getsexact bounds {1,1} (always executes) and the dead region gets {0,0} (never executes).
How do we test this?
unittests/Optimizer/IfOpConstantFoldTest.cppdirectly call both methodswith constant and non-constant operands and assert the correct regions/bounds are returned.
test/Transforms/cc_if_const_fold.qkeverifies end-to-end behavior