MIPS if greater or equals to - if-statement

if ($t4 >= $5)
$t8 = $t8+1
Given that pseudo-code, I put this attempt together based on various sources. Seems simple but i am still learning the foundations. Not too sure if this is correct.
slt $t1, $t5, $t4
beq $t0, $zero, endLoop
addi $8, $8, 1
Main reference: Greater than, less than equal, greater than equal in MIPS

You have some typos:
Your branch instruction is testing $t0, but the target of the slt is $t1 so that is a mismatch.
You have a conditional branch instruction with a label, but don't define the label.
Your label name is endLoop, but this is just an if, not a while or other loop condition, and the the statement controlled by the if isn't a break.
Otherwise looks like you have the right idea.  But this is tricky stuff to get right.
To be clear, you are aware that we have to reverse (negate re: boolean logic) the sense of the condition for assembly language's if-goto style, as compared with structured programming's if-then construct.
if (t4 >= t5)
t8++;
becomes
if (t4 < t5) goto skip; // !(a >= b) ---> a < b
t8++;
skip: ;
Now, I would have written the above more directly in assembly:
slt $t1, $t4 $t5 # let's see if t4 < t5
bne $t1, $zero, skip # yes? goto skip
addi $t8,$t8,1
skip:
Instead you have reversed the operands $t4 and $t5, and then also reversed the branch condition: beq vs. my bne.  This is very close to a triple negation of the (structured style) C (and this would have worked), but there is a subtle difference.
So, what you have written is:
if (!(t5 < t4)) goto skip;
t8++;
skip: ;
which — translated to structure programming — is:
if (t5 < t4) // logically: remove the negation and incorporate then
t8++;
and we can see that if we reverse the operands but also switch the relation, we have:
if (t4 > t5) // same exact logical condition as immediately above
t8++;
So, your code does not produce the same condition test as the C code, since the operation under equality is different from the original.
You assembly code is doing t4 > t5, and the C code is doing t4 >= t5.  See the difference?
This stuff is tricky because:
We have to reverse (negate) the condition when going between structured statement and if-goto style, and,
MIPS provides only one of the ordered relational operations (it has < but not <=, >, >=), and so, that means when we need what would have been sge we have to simulate it (via slt by reversing operands and/or reversing the branch on true vs. branch false).
Related:
Mutiple conditions in if in MIPS - if( x<y && x<z ) or similar. One way is to compare into booleans and AND or OR them together, instead of short-circuiting by doing multiple branches.
How can I implement if(condition1 && condition2) in MIPS? - if (x < 10 && x > 5) or similar: with two branches, or with the range-check trick.
How to do less than or equal in Assembly Language(MIPS)? - compare into boolean integer for conditions other than slt

Related

How can I write an LLVM pass to detect redundant conditions in C / C + +

I want to write an LLVM pass to detect redundant condition pattern like this in c++.
int a = ... , b = ..., c = ...
//first if condition
if(a == b + 1 - c){
...//compoundStmt1
}
// not change the val of a, b ,c
...
//second if condition which is equivalent to first one
if(c == b - a + 1){ // redundant condition
... //compoundStmt2
}
If I am able to find the equivalent condition, I may merge compoundStmt1 and CompoundStmt2.(That's my target!)
For this case, my idea is to find all conditional statements in C + + on CFG by checking whether the last sentence is a conditional branch jump instruction and the condition is ICMP or FCMP instruction, and add them to subsequent nodes, add the conditional constraints of the current node, and continue to spread to successors.
But I thought later that for the second if statement, it would actually be added a == b + 1 - c and a != b + 1 - c, which are actually equivalent to not adding them. How should I deal with it and judge that the second encounter of c == b - a + 1 is repeated with the first one before to find out this redundant condition case.
====================
for complicated case(such as string's "==" operator call), how can I do something to check that.
string s = "...."
//first if stmt
if(s == "abc"){
...
}
// not reassign s
...
...
//second if stmt with same condition
if("abc" == s){ // redundant condition
...
}
In fact the first case is much harder to do:
a == b + 1 - c
c == b - a + 1
In LLVM IR the right side would have only two operands for arithmetic operations. So for simplicity let's assume we need to establish equivalence between:
a == b - c
c == b - a
In LLVM this could look like:
%a1 = sub %b, %c
%cmp1 = ceq %a, a1
%c1 = sub %b, %a
%cmp2 = ceq %c, c1
And the goal is to establish that %cmp1 and %cmp2 are identical. You can think of the operations in terms of DAG (Directed Acyclic Graphs) or Trees in most cases e.g.,
cmp1(ceq)
/ \
%a1(sub) %a
/ \
%b %c
cmp2(ceq)
/ \
%c1(sub) %c
/ \
%b %a
To establish equivalence you need to make a set of tree transforms that makes both trees identical. There are algorithms to establish Tree equivalence and, unsurprisingly, first proposed by the authors of the Dragon Book. For simple cases like small trees (<=5 nodes) and limited operands(arithmetic), you can just choose some heuristics to find equivalence. In case the sub-graph can't be reduced to a Tree and you are stuck with a DAG, it would be wiser to bail out in the interest of compile time as DAG isomorphism isn't cheap to establish
Even after equivalence is established, you need to check for certain invariants like dominance, non-intersecting side-effects etc. I have described few things below for the second case.
For the second case
The problem is there is no built in operator to compare strings. So the equality will look like a function call and it becomes a non-trivial problem then. But assuming you only want to compare scalars like int. e.g.,
s == 10
// s is not modified
10 == s
In LLVM IR this may look like:
%t1 = 10
%c1 = ceq %s, %t1 # ceq = compare equal
// s is not modified.
%t2 = 10
%c2 = ceq %t2, %s
The first step is to make sure that s is not modified.
In some cases you may get this for 'free' in SSA representation. SSA is a declarative representation, so each variable is defined once.
The second step is to do 'constant propagation'.
So %t2 will removed after that.
%t1 = 10
%c1 = ceq %s, %t1
// s is not modified.
%c2 = ceq %t1, %s
Third step is to canonicalize the operands.
You may sort the operands in some order e.g., lexicographic order
%t1 = 10
%c1 = ceq %s, %t1
// s is not modified.
%c2 = ceq %s, %t1
Fourth step is to 'hash' the instructions.
With hash you can find the identical operations. Compilers use 'GVN' as hashing mechanism. GVN also accounts for ordering as described in step 3. So with GVN you can skip the third step.
Fifth step is to establish 'dominance'.
Essentially, all paths from the beginning of the function to %c2 must pass through %c1. Then only one can replace %c2 with %c1. There are APIs which makes this check trivial.
In case we want to handle the original problem of detecting that the string comparisons are equivalent, we need to hard-code the semantics of strcmp. For example, knowing that strcmp(a, b) and strcmp(b, a) will return the same value (0) when a == b. And then performing 'canonicalization of operations followed by remaining steps described above; it is tricky but doable.
References:
GVN-PRE is an optimization in LLVM that does what I described for the second case. There might be more checks needed for anticipability, and non-intersecting side effects, depending on the operand+operation types. What I described here is a very simple example.
GVNHoist is another optimization that has similar checks you can find useful.

Checking if a given group of integers contains a 0 value

Suppose I have a bunch of integers (10~20) and need to check if any of them equals 0. What's the most efficient way to do it? I don't want to evaluate a giant if(a=0 || b=0 || c=0 ||...) statement. I thought of if(abc... = 0) but if I remember correctly multiplication isn't a very quick process. Are there any other tricks, such as bit wise operations that would work? I'm trying to think as low level as possible to make this super efficient.
I'm pretty sure the fastest and clearest way to do this is with an explicit test:
int has_zero = !a || !b || !c || !d || !e ...;
Because the || and && are short-circuiting operators in C, evaluation stops as soon as the final result is known, so if (for instance) the b variable is zero, that satisfies the expression as true and stops evaluating the rest.
#AbhayAravinda suggested that !(a && b && c && d ...) might be more efficient, but I don't think so; because this is not so much doing an explicit not operation, but a low-level test-against-zero, this is a really easy test for pretty much any architecture to do reliably. I did a quick look at optimized assembler for both versions and there was no clear winner for performance, but I think the first version is clearer.
If every single cycle matters, then check both versions on your platform, but on my 64-bit Intel system, both gcc and clang do in fact generate the same assembly for both versions (with optimizations turned on).
Simple test code:
int a, b, c, d, e, f;
int test_or()
{
return !a || !b || !c || !d || !e || !f;
}
int test_and()
{
return ! (a && b && c && d && e && f);
}
int main()
{
return test_or() | test_and();
}
Compile this with gcc -S -O testfile.c and look at the resulting .s file.
Test each one in turn. Exploit the short-circuiting property of ||; place the variables in descending order of the probability of each being zero:
if (!a/*most likely to be zero*/ || !b || ...){
// one of them is zero
}
Most people give an answer like:
!a || !b || ...
(where a is the most probable one of being zero)
The idea is that, in case a is zero, then the rest of the sequence is not evaluated (because of not being necessary), which is a kind of optimisation, performed by the compiler.
This turns the question into: does your compiler perform this optimisation or not (and in case of "possibly yes", what are the parameters in order to enforce this)?
Can you tell us which compiler (version) you're working with? This might enable us verifying this.
You may look at the assembler output.
The !a || !b || !c || !d || !e || !f will give you a bunch of cmp and je statements. One pair for each variable. Because of boolean short cut evaluation, it may run very fast. Or not.
The maybe better and deterministic solution is using the bitwise AND operator. If one operand is 0, then the result will be 0. So someting like:
if (a & b & c & d & e & f & g & h & i & j & k)
will result in one mov and then and statements for each variable.
So, if the variable that is 0 is in the 2nd half of the if statement, then the bitweise AND will be faster.

If-Else with nested If in MIPS assembly

I am trying to code something that continually takes in an integer from the user and stores the minimum value into $s2.
This is a C code representation of what I am trying to do
if ( $s2 == 0 )
$s2 = $t0
else {
if ( $t0 < $s2 )
$s2 = $t0
}
Basically, I loaded $s2 with zero outside of the input loop. This checks if $s2 has zero, and sets it to the current (first) user input ($t0) since that is the minimum value. If $s2 no longer contains zero then it checks the new user input against what is already in $s2 and if it is less than it becomes the new minimum value.
How can I implement this in MIPS assembly?
I have this so far (this is the end piece of a loop called read) but all it does is when I press the first int, it skips to the end and prints the min without looping over.
read:
...
beq $s2, $zero, LOAD
slt $s6, $t0, $s2
bne $s6, $zero, LOAD
j read
LOAD:
li $s2, 0
addu $s2, $s2, $t0
The main problem is that you need a jump at the bottom of your code because you're [probably] "falling off the edge of the world":
read:
...
beq $s2,$zero,LOAD
slt $s6,$t0,$s2
bne $s6,$zero,LOAD
j read
LOAD:
# NOTE: you could use $zero as you did above to eliminate the "li" here
li $s2,0
addu $s2,$s2,$t0
# NOTE/BUG: need to jump back to read loop
j read
The code can be shortened a bit.
From the slt (vs. sltu) we know that the values are signed. So, if we prefill $s0 with the maximum positive value (i.e. 0x7FFFFFFF) instead of zero, we can remove the first beq from the loop.
Also, if we reverse the sense of the branch after the slt, we can eliminate an extra j instruction.
We can change the addu to use $zero and eliminate the li
li $s2,0x7FFFFFFF # load maximum positive value
read:
...
slt $s6,$t0,$s2 # is new value < minimum?
beq $s6,$zero,read # if no, loop
addu $s2,$zero,$t0 # save new minimum value
j read # restart input loop

how can you translate the statement if(isalpha(c)) from C++ to MIPS? [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am trying to translate the statement if(isalpha(c)), where c is a char variable, from C++ to MIPS assembly. I tried to google it, but I could not find an answer. Does anyone have any idea? Thanks for your time.
I'm just going to demonstrate one possible way, which is not efficient or "cool", but it's simple.
So, you want an equivalent of this C block:
if (isalpha(c))
{
/* Do stuff... */
}
Which is like this, considering how isalpha() works:
if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
{
/* Do stuff... */
}
But there are no "block" structures in assembly. Everything is a jump (or a goto in C, which you should never use.) So, to get closer to the assembly version, we might modify our C code to use a jump:
if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')))
goto AfterStuff;
/* Do stuff... */
AfterStuff:
Note that we are jumping over the "Do stuff" part if the reverse of our condition was true.
Now, assuming we know that 'A' < 'Z' < 'a' < 'z' (the ASCII codes are, respectively: 65, 90, 97, 122,) then we can rewrite the above code like this:
if (c < 65)
goto AfterStuff;
if (c <= 90)
goto DoStuff;
if (c < 97)
goto AfterStuff;
if (c > 122)
goto AfterStuff;
DoStuff:
/* Do stuff... */
AfterStuff:
Note that if c is less than 'A', we jump after the stuff. But if after comparing c and 'A', we find out that c is not only greater or equal to 'A' (because we didn't jump away,) but it's also less than or equal to 'Z', we jump directly to the "stuff" and don't check anything else. Also, the operands of the last blt instruction are reversed.
The assembly gets a little complicated, because we have to load the required immediates into registers and whatnot. Here's the code:
lb $t0, ($s0) # assuming address of c is in s0 register
addi $t1, $zero, 65 # set t1 = 'A'
blt $t0, $t1, AfterStuff # if (c < 'A') goto AfterStuff
addi $t1, $zero, 90 # set t1 = 'Z'
ble $t0, $t1, DoStuff # if (c <= 'Z') goto DoStuff
addi $t1, $zero, 97 # set t1 = 'a'
blt $t0, $t1, AfterStuff # if (c < 'a') goto AfterStuff
addi $t1, $zero, 122 # set t1 = 'z'
blt $t1, $t0, AfterStuff # if ('z' < c) goto AfterStuff
DoStuff:
# Do whatever you want to do
AfterStuff:
I believe the above works, but I absolutely can't be sure. It has been more than a decade since I wrote any MIPS assembly code (or any other code for a MIPS) and I was never very proficient anyways.

How to convert a three address code to MIPS Assembly language?

I am doing a project in which I have to create a translator that would generate a MIPS assembly code for a C code. The programming language that am using is C++ and I have done till generation of three address code and am really confused about how to proceed further.
As already stated, it's a direct translation. There's really nothing to clarify. As an example, take the following three-address code:
i := 0 ; assignment
L1: if i >= 10 goto L2 ; conditional jump
t0 := i*i
t1 := &b ; address-of operation
t2 := t1 + i ; t2 holds the address of b[i]
*t2 := t0 ; store through pointer
i := i + 1
goto L1
L2:
The MIPS translation is:
li $t0, 0 #allocator assigned i to t0
L1: bge $t0, 10, L2
mult $t1, $t0, $t0
la $t2, b
add $t3, $t2, $t0
sw $t1, ($t3)
addi $t0, $t0, 1
j L1
L2:
If your lucky enough to have three-address like that, you barely have to do anything. Find the corresponding opcode to go with the instruction. The register allocation has already been done. If the three-address code is literally a bunch a strings, I'd consider writing a small parser (using a generator) instead of trying to extract information from the strings.