https://llvm.org/bugs/show_bug.cgi?id=29127
Bug ID: 29127 Summary: load/store address constant offsets with negative register values Product: libraries Version: trunk Hardware: PC OS: Linux Status: NEW Severity: normal Priority: P Component: Backend: WebAssembly Assignee: unassignedb...@nondot.org Reporter: dsch...@google.com CC: llvm-bugs@lists.llvm.org Classification: Unclassified Created attachment 17038 --> https://llvm.org/bugs/attachment.cgi?id=17038&action=edit input IR The following C code: int args[32]; int main() { int i; #pragma clang loop unroll(disable) for (i=0;i<32;i++) args[i]=1; return 0; } compiles with -O to the following IR: @args = hidden local_unnamed_addr global [32 x i32] zeroinitializer, align 16 ... for.body: ; preds = %for.body, %entry %i.04 = phi i32 [ 0, %entry ], [ %inc, %for.body ] %arrayidx = getelementptr inbounds [32 x i32], [32 x i32]* @args, i32 0, i32 %i.04 store i32 1, i32* %arrayidx, align 4, !tbaa !1 When the backend runs loop strength reduction, it becomes this: for.body: ; preds = %for.body, %entry %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ -128, %entry ] %lsr.iv1 = inttoptr i32 %lsr.iv to i32* %uglygep = getelementptr i8, i8* bitcast ([32 x i32]* @args to i8*), i32 %lsr.iv %uglygep2 = bitcast i8* %uglygep to i32* %scevgep = getelementptr i32, i32* %uglygep2, i32 32 store i32 1, i32* %scevgep, align 4, !tbaa !1 After SelectionDAGBuilder we get %vreg0 = -128 ... store(1, add( add(GlobalAddr<@args>, %vreg0), 128)) Which the DAGcombiner reduces to %vreg0 = -128 store(1, add(%vreg0, Wrapper(TGlobalAddr<@args>+128))) and then selects to # BB#0: # %entry i32.const $0=, -128 .LBB0_1: # %for.body # =>This Inner Loop Header: Depth=1 loop # label0: i32.const $push4=, 1 i32.store $drop=, args+128($0), $pop4 The problem is that the address calculation: @args+128 + $0 (where $0 starts at -128) is unsigned, so it overflows. It seems there are a couple places we could prevent this: One is in the LSR/SCEV cost modeling/formula selection. LSR chooses an address formula it prints as @args + 128 + reg({-128,+,4}<nuw><nsw><%for.body>) isLegalAddressingMode seems like it might be a way to disallow this, but it doesn't quite cover it because GV + offset + reg is legal and we want to allow it (currently we allow it if offset >= 0); the problem here is that LSR has chosen a negative value range for the register. This can be disabled by e.g. hacking Cost::RateFormula (LoopStrengthReduce.cpp:1130) to cause a SCEV BaseReg to "Lose" (i.e. not be selected) if it has a known negative value (or do something equivalent to that). Changing the cost model or selection this way might entail adding something to TargetTransformInfo alongside isLegalAddressingMode (i.e. if the target address calculation is unsigned or something like that). That selection is sort of the deepest cause of the problem. Another way might be to prevent one of the other events down the chain. e.g. the dag combiner folds the add(GlobalAddr<@args>, %vreg0) but that seems legit, and isel folds the GA expression into the constant offset which it seems like we'd want, and there are some subtleties around the changes we made to how the nsw/nuw flags are treated that I'm not sure I fully understand yet, so I don't yet see an obvious way to fix this there without disallowing other things we do want to allow. I'm also not clear whether there are other potential sources of similar issues, i.e. a register with a negative value combined with a constant offset. -- You are receiving this mail because: You are on the CC list for the bug.
_______________________________________________ llvm-bugs mailing list llvm-bugs@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs