<html><body><p><font size="2">Hi,</font><br><br><font size="2">While comparing the code by LLVM and GCC for some major libraries, I found that LLVM fails to apply jump threading with a method whose return type is std::pair<int, bool> (actually, any pair of 32-bit values like std::pair<bool, int> and std::pair<int, int>).</font><br><font size="2">For example, jump threading does not work for the if statement in func.</font><br><br><font size="2">std::pair<int, bool> callee(int v) {</font><br><font size="2"> int a = dummy(v);</font><br><font size="2"> if (a) return std::make_pair(dummy(v), true);</font><br><font size="2"> else return std::make_pair(v, v < 0);</font><br><font size="2">}</font><br><br><font size="2">int func(int v) {</font><br><font size="2"> std::pair<int, bool> rc = callee(v);</font><br><font size="2"> if (rc.second) {</font><br><font size="2"> // do something</font><br><font size="2"> }</font><br><font size="2"> ...</font><br><br><font size="2">SROA executed before the method inlining replaces std::pair by i64 without splitting in both `callee` and `func` since at this point no access to the individual fields is seen to SROA.</font><br><font size="2">After inlining, jump threading fails to identify that the incoming value is a constant due to additional instructions (like or, and, trunc). </font><br><br><font size="2">I would appreciate it if I could have any suggestions on how we can optimization such cases.</font><br><font size="2">I am planning to enhance InstCombine pass to eliminate these additional instructions before jump threading rather than enhancing SROA or jump threading.</font><br><br><br><font size="2">Here is LLVM IR generated for above C code.</font><br><br><font size="2">define signext i32 @_Z4funci(i32 signext %v) local_unnamed_addr #0 {</font><br><font size="2">entry:</font><br><font size="2"> %call.i = tail call signext i32 @_Z5dummyi(i32 signext %v)</font><br><font size="2"> %tobool.i = icmp eq i32 %call.i, 0</font><br><font size="2"> br i1 %tobool.i, label %if.else.i, label %if.then.i</font><br><br><font size="2">if.then.i: ; preds = %entry</font><br><font size="2"> %call1.i = tail call signext i32 @_Z5dummyi(i32 signext %v)</font><br><font size="2"> %retval.sroa.0.0.insert.ext.i.i = zext i32 %call1.i to i64</font><br><font size="2"> br label %_ZL6calleei.exit</font><br><br><font size="2">if.else.i: ; preds = %entry</font><br><font size="2"> %.lobit.i = lshr i32 %v, 31</font><br><font size="2"> %0 = zext i32 %.lobit.i to i64</font><br><font size="2"> %retval.sroa.2.0.insert.shift.i8.i = shl nuw nsw i64 %0, 32</font><br><font size="2"> %retval.sroa.0.0.insert.ext.i9.i = zext i32 %v to i64</font><br><font size="2"> br label %_ZL6calleei.exit</font><br><br><font size="2">_ZL6calleei.exit: ; preds = %if.then.i, %if.else.i</font><br><font size="2"> %.sink = phi i64 [ 4294967296, %if.then.i ], [ %retval.sroa.0.0.insert.ext.i9.i, %if.else.i ]</font><br><font size="2"> %retval.sroa.0.0.insert.ext.i.i.sink = phi i64 [ %retval.sroa.0.0.insert.ext.i.i, %if.then.i ], [ %retval.sroa.2.0.insert.shift.i8.i, %if.else.i ]</font><br><font size="2"> %retval.sroa.0.0.insert.insert.i.i = or i64 %retval.sroa.0.0.insert.ext.i.i.sink, %.sink</font><br><font size="2"> %rc.sroa.0.0.extract.trunc = trunc i64 %retval.sroa.0.0.insert.insert.i.i to i32</font><br><font size="2"> %1 = and i64 %retval.sroa.0.0.insert.insert.i.i, 4294967296</font><br><font size="2"> %tobool = icmp eq i64 %1, 0</font><br><font size="2"> br i1 %tobool, label %if.end, label %if.then ; <<- not jump threaded</font><br><br><font size="2"><br>-----<br>Hiroshi Inoue <inouehrs@jp.ibm.com><br>IBM Research - Tokyo<br></font><BR>
</body></html>