Hi!
when using something like
(a < b) ? a : b
I would expect that the select instruction is always used.
But, if a or b are a global variable, a real branch with multiple
basic blocks is created. Is this a bug or a feature?
-Jochen
Hi!
when using something like
(a < b) ? a : b
I would expect that the select instruction is always used.
But, if a or b are a global variable, a real branch with multiple
basic blocks is created. Is this a bug or a feature?
-Jochen
It's a feature. It is up to the optimizer to form the select. If a or b is volatile (or if they are other expressions with side effects), the transformation is invalid.
-Chris
Hello Jochen-
Your expectation is incorrect, I'm afraid. Typically this would be expanded
to something like this:
…
%cmp = …
br i1 %cmp, label %ternary.true, label %ternary.false
ternary.true:
%truevalue = …
br label %ternary.end
ternary.false:
%falsevalue = …
br label %ternary.end
ternary.end:
%value = phi %type [%truevalue, %ternary.true], [%falsevalue, %ternary.false]
This may then be optimised to a select by later passes, if it's considered to be
profitable to do so.
The reason for this is that C requires that only the value which is needed
is evaluated. If one of the selected values has a side effect, this becomes significant.
Alistair
The reason for this is that C requires that only the value which is needed
is evaluated. If one of the selected values has a side effect, this becomes significant.
Ah, I see. But in my case I have only normal variables (local or global), no volatile and no functions.
Therefore I wonder why the optimizer misses it in some cases (with globals).
-Jochen
It normally gets optimized... can you attach a testcase?
-Eli
This is by design, generating a select requires analyzing the operands
in the ?: operator to determine whether they have side effects. We
generally prefer to leave those kinds of optimizations to the backend,
unless there is a clear compile time opportunity.
- Daniel
It normally gets optimized... can you attach a testcase?
This is my testcase:
float a;
float b;
float x;
extern "C" void main()
{
x = a > b ? a : b;
}
This are my optimizations:
llvm::PassManager passManager;
passManager.add(new llvm::TargetData(targetDescription));
passManager.add(llvm::createFunctionInliningPass(2000));
passManager.add(llvm::createScalarReplAggregatesPass(1000000));
passManager.add(llvm::createInstructionCombiningPass());
passManager.add(llvm::createDeadInstEliminationPass());
passManager.add(llvm::createDeadStoreEliminationPass());
passManager.add(llvm::createDeadTypeEliminationPass());
This my language options
langOptions.Bool = 1;
langOptions.CPlusPlus = 1;
langOptions.RTTI = 0;
langOptions.AltiVec = 1;
langOptions.Freestanding = 1;
-Jochen